Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Closing an old fork |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk-fork |
Files: | files | file ages | folders |
SHA1: |
832a5fc594b616006f0cdb2604a8f6a2 |
User & Date: | seandeelywoods 2016-06-28 12:18:31.646 |
Context
2016-06-28
| ||
12:42 | Now really close older fork check-in: 3c606ccbc8 user: jan.nijtmans tags: trunk | |
12:18 | Closing an old fork Closed-Leaf check-in: 832a5fc594 user: seandeelywoods tags: trunk-fork | |
2016-06-03
| ||
16:04 | [b35544d2c8] Bump version in docs to 2.8 check-in: 58dcd71724 user: gahr tags: trunk | |
2015-10-15
| ||
22:27 | Updating to the latest shed check-in: 343442494c user: seandeelywoods tags: trunk-fork | |
Changes
Added .fossil-settings/crnl-glob.
> > > > > | 1 2 3 4 5 | win/thread-win.dsp win/thread-win.dsw win/makefile.vc win/pkg.vc win/rules.vc |
Added .fossil-settings/encoding-glob.
> > > > > | 1 2 3 4 5 | win/thread-win.dsp win/thread-win.dsw win/makefile.vc win/pkg.vc win/rules.vc |
Changes to ChangeLog.
1 2 3 4 5 6 7 | 2013-05-23 Jan Nijtmans <[email protected]> * generic/threadSvKeylistCmd.c: Change a few internal variable * generic/threadSvListCmd.c: from type int to type size_t. * generic/threadCmd.c: Simplify determination of whether Tcl is compiled with thread support. * configure: re-generate with latest TEA. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | 2016-06-03 Pietro Cerutti <[email protected]> * doc/*: Bump version to 2.8 in docs [Tkt b35544d2c8] 2016-06-03 Pietro Cerutti <[email protected]> * generic/threadCmd.c: Add parenthesis to bit-shift macros [Tkt 957dbe231c] 2016-05-31 Pietro Cerutti <[email protected]> * generic/threadSvCmd.c: Implement [tsv::handlers] command [Tkt 72b8ee4c76] * doc/html/tsv.html * doc/man/tsv.n * doc/tsv.man * tests/tsv.test 2016-05-31 Pietro Cerutti <[email protected]> * generic/threadCmd.c: Add status arg to [thread::exit] [Tkt 3407860fff] * tests/thread.test * doc/thread.man * doc/man/thread.n * doc/html/thread.html 2016-05-18 Pietro Cerutti <[email protected]> * generic/threadSvCmd.c: Fix race condition in thread finalization routine [Tkt 3532972fff] * tests/tkt-84be1b5a73.test: Add a test for [Tkt 84be1b5a73] 2016-05-17 Pietro Cerutti <[email protected]> * generic/threadCmd.c: Fix -async and result trace [Tkt 84be1b5a73] * doc/thread.man: Remove "id" arg from [thread::broadcast]'s manpage * doc/man/thread.n: Regenerate documentation * doc/html/thread.html 2016-05-13 Pietro Cerutti <[email protected]> * aclocal.m4: Add support for LMDB persistent storage [Tkt 9378bb6795] * configure * configure.ac * doc/html/tsv.html * doc/man/tsv.n * doc/tsv.man * generic/psGdbm.c * generic/psLmdb.c * generic/psLmdb.h * generic/threadSvCmd.c * generic/threadSvCmd.h * tests/French.txt version * tests/store-load.tcl * tests/tsv.test * generic/tclThreadInt.h: Use spaces for indentation everywhere * generic/tclXkeylist.c * generic/threadCmd.c * generic/threadNs.c * generic/threadSpCmd.c * generic/threadSpCmd.h * generic/threadSvCmd.c 2016-04-20 Pietro Cerutti <[email protected]> * configure, aclocal.m4: Correctly handle --without-gdbm [Tkt f8ff429a39] * doc/tsv.man: Document side-effect of [tsv::array unbind] [Tkt be135da5f9] * doc/*.(html|n): Regenerate documentation [Tkt 41922d3bb7] * generic/threadSvCmd.c: Avoid double query to persistent storage in tsv::array bind [Tkt a135697d8c] 2013-05-23 Jan Nijtmans <[email protected]> * generic/threadSvKeylistCmd.c: Change a few internal variable * generic/threadSvListCmd.c: from type int to type size_t. * generic/threadCmd.c: Simplify determination of whether Tcl is compiled with thread support. * configure: re-generate with latest TEA. |
︙ | ︙ |
Changes to Makefile.in.
︙ | ︙ | |||
147 148 149 150 151 152 153 | INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ #INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@ PKG_CFLAGS = @PKG_CFLAGS@ # TCL_DEFS is not strictly need here, but if you remove it, then you | | | 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ #INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@ PKG_CFLAGS = @PKG_CFLAGS@ # TCL_DEFS is not strictly need here, but if you remove it, then you # must make sure that configure.ac checks for the necessary components # that your library may use. TCL_DEFS can actually be a problem if # you do not compile with a similar machine setup as the Tcl core was # compiled with. #DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS) DEFS = @DEFS@ $(PKG_CFLAGS) # Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile |
︙ | ︙ | |||
350 351 352 353 354 355 356 | #======================================================================== # End of user-definable section #======================================================================== #======================================================================== # Don't modify the file to clean here. Instead, set the "CLEANFILES" | | | 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | #======================================================================== # End of user-definable section #======================================================================== #======================================================================== # Don't modify the file to clean here. Instead, set the "CLEANFILES" # variable in configure.ac #======================================================================== clean: -test -z "$(BINARIES)" || rm -f $(BINARIES) -rm -f *.$(OBJEXT) core *.core -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) |
︙ | ︙ |
Changes to aclocal.m4.
︙ | ︙ | |||
18 19 20 21 22 23 24 | # AC_DEFUN(TCLTHREAD_WITH_GDBM, [ AC_ARG_WITH(gdbm, [ --with-gdbm link with optional GDBM support],\ with_gdbm=${withval}) | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # AC_DEFUN(TCLTHREAD_WITH_GDBM, [ AC_ARG_WITH(gdbm, [ --with-gdbm link with optional GDBM support],\ with_gdbm=${withval}) if test x"${with_gdbm}" != x -a "${with_gdbm}" != no; then AC_MSG_CHECKING([for GNU gdbm library]) AC_CACHE_VAL(ac_cv_c_gdbm,[ if test x"${with_gdbm}" != x -a "${with_gdbm}" != "yes"; then if test -f "${with_gdbm}/gdbm.h" -a x"`ls ${with_gdbm}/libgdbm* 2>/dev/null`" != x; then ac_cv_c_gdbm=`(cd ${with_gdbm}; pwd)` |
︙ | ︙ | |||
66 67 68 69 70 71 72 73 | GDBM_CFLAGS="-I\"$gincdir\"" GDBM_LIBS="-L\"$glibdir\" -lgdbm" fi fi fi ]) # EOF | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | GDBM_CFLAGS="-I\"$gincdir\"" GDBM_LIBS="-L\"$glibdir\" -lgdbm" fi fi fi ]) # # Handle the "--with-lmdb" option for linking-in # the LMDB-based peristent store for shared arrays. # It tries to locate LMDB files in couple of standard # system directories and/or common install locations # in addition to the directory passed by the user. # In the latter case, expect all LMDB lib files and # include files located in the same directory. # AC_DEFUN(TCLTHREAD_WITH_LMDB, [ AC_ARG_WITH(lmdb, [ --with-lmdb link with optional LMDB support], with_lmdb=${withval}) if test x"${with_lmdb}" != "x" -a "${with_lmdb}" != no; then AC_MSG_CHECKING([for LMDB library]) AC_CACHE_VAL(ac_cv_c_lmdb,[ if test x"${with_lmdb}" != x -a "${with_lmdb}" != "yes"; then if test -f "${with_lmdb}/lmdb.h" -a x"`ls ${with_lmdb}/liblmdb* 2>/dev/null`" != x; then ac_cv_c_lmdb=`(cd ${with_lmdb}; pwd)` lincdir=$ac_cv_c_lmdb llibdir=$ac_cv_c_lmdb AC_MSG_RESULT([found in $llibdir]) else AC_MSG_ERROR([${with_lmdb} directory doesn't contain lmdb library]) fi fi ]) if test x"${lincdir}" = x -o x"${llibdir}" = x; then for i in \ `ls -d ${exec_prefix}/lib 2>/dev/null`\ `ls -d ${prefix}/lib 2>/dev/null`\ `ls -d /usr/local/lib 2>/dev/null`\ `ls -d /usr/lib 2>/dev/null` ; do if test x"`ls $i/liblmdb* 2>/dev/null`" != x ; then llibdir=`(cd $i; pwd)` break fi done for i in \ `ls -d ${prefix}/include 2>/dev/null`\ `ls -d /usr/local/include 2>/dev/null`\ `ls -d /usr/include 2>/dev/null` ; do if test -f "$i/lmdb.h" ; then lincdir=`(cd $i; pwd)` break fi done if test x"$llibdir" = x -o x"$lincdir" = x ; then AC_MSG_ERROR([none found]) else AC_MSG_RESULT([found in $llibdir, includes in $lincdir]) AC_DEFINE(HAVE_LMDB) LMDB_CFLAGS="-I\"$lincdir\"" LMDB_LIBS="-L\"$llibdir\" -llmdb" fi fi fi ]) # EOF |
Changes to configure.
more than 10,000 changes
Changes to configure.ac.
1 2 3 4 5 6 | #!/bin/bash -norc dnl This file is an input file used by the GNU "autoconf" program to dnl generate the file "configure", which is run during Tcl installation dnl to configure the system for the local environment. #----------------------------------------------------------------------- | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #!/bin/bash -norc dnl This file is an input file used by the GNU "autoconf" program to dnl generate the file "configure", which is run during Tcl installation dnl to configure the system for the local environment. #----------------------------------------------------------------------- # Sample configure.ac for Tcl Extensions. The only places you should # need to modify this file are marked by the string __CHANGE__ #----------------------------------------------------------------------- #----------------------------------------------------------------------- # __CHANGE__ # Set your package name and version numbers here. # # This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION # set as provided. These will also be added as -D defs in your Makefile # so you can encode the package version directly into the source files. #----------------------------------------------------------------------- AC_INIT([thread], [2.8.0]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. #-------------------------------------------------------------------- |
︙ | ︙ | |||
70 71 72 73 74 75 76 77 78 79 80 81 82 83 | #-------------------------------------------------------------------- # Check if building with optional Gdbm package. This will declare # GDBM_CFLAGS and GDBM_LIBS variables. #-------------------------------------------------------------------- TCLTHREAD_WITH_GDBM #-------------------------------------------------------------------- # Locate the NaviServer/AOLserver dir for compilation as NaviServer/AOLserver module. # This will declare NS_INCLUDES, NS_LIBS and define NS_AOLSERVER. #-------------------------------------------------------------------- NS_PATH_AOLSERVER | > > > > > > > | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | #-------------------------------------------------------------------- # Check if building with optional Gdbm package. This will declare # GDBM_CFLAGS and GDBM_LIBS variables. #-------------------------------------------------------------------- TCLTHREAD_WITH_GDBM #-------------------------------------------------------------------- # Check if building with optional lmdb package. This will declare # LMDB_CFLAGS and LMDB_LIBS variables. #-------------------------------------------------------------------- TCLTHREAD_WITH_LMDB #-------------------------------------------------------------------- # Locate the NaviServer/AOLserver dir for compilation as NaviServer/AOLserver module. # This will declare NS_INCLUDES, NS_LIBS and define NS_AOLSERVER. #-------------------------------------------------------------------- NS_PATH_AOLSERVER |
︙ | ︙ | |||
94 95 96 97 98 99 100 101 102 103 104 105 106 107 | TEA_ADD_SOURCES([generic/threadNs.c \ generic/threadCmd.c \ generic/threadSvCmd.c \ generic/threadSpCmd.c \ generic/threadPoolCmd.c \ generic/psGdbm.c \ generic/threadSvListCmd.c \ generic/threadSvKeylistCmd.c \ generic/tclXkeylist.c \ ]) TEA_ADD_HEADERS([generic/tclThread.h]) TEA_ADD_INCLUDES([${NS_INCLUDES}]) | > | | | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | TEA_ADD_SOURCES([generic/threadNs.c \ generic/threadCmd.c \ generic/threadSvCmd.c \ generic/threadSpCmd.c \ generic/threadPoolCmd.c \ generic/psGdbm.c \ generic/psLmdb.c \ generic/threadSvListCmd.c \ generic/threadSvKeylistCmd.c \ generic/tclXkeylist.c \ ]) TEA_ADD_HEADERS([generic/tclThread.h]) TEA_ADD_INCLUDES([${NS_INCLUDES}]) TEA_ADD_LIBS([${GDBM_LIBS} ${LMDB_LIBS} ${NS_LIBS}]) TEA_ADD_CFLAGS([${GDBM_CFLAGS} ${LMDB_CFLAGS}]) TEA_ADD_STUB_SOURCES([]) TEA_ADD_TCL_SOURCES([lib/ttrace.tcl]) #-------------------------------------------------------------------- # __CHANGE__ # A few miscellaneous platform-specific items: # |
︙ | ︙ |
Changes to doc/html/thread.html.
|
| | < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | | | < | | | | | | < < | < | | | | > > | > | | | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | < | > > | < | | | < | | | | < < < < < < | | | | | | | < < < | | | < < < | | | < < < < | | | | < < < | | | | < | < | | | | | < < < | | | | | | < < < < < | | | < < < | | | < < < < | | | | < < < | | | | < < | < < | | < < < < | | | | | | | < | | < | | | > > > > > > > > > | | | | < | | | | < < < < < | | | | < | | > | | | | < | < < | < | | | < < < | < < | | | < < < < < | | | < | < < | | | | | < | < | | < < < | | | | < < < < < | | | < < < < | | | | | | | < | | < < | < | | | | < < < < < | | | < < < < < | | | < | < < | | | | | | < < < | | | < < < < < | | | | < < < | | | < | | < < | < | | | | < < < < | | | | < < < < | | < | | < < < | | < < | < < < | | | | | < < < < | | | < < < < | | | < < < < | | < | | < < < < < | | < | | < < < | | < < | < < < | | | < < < < | | | < < < < | | | < < < < | | | | < < < < | | < | | < < < < < | | < < < | | < < | < < < | | | < < < < | | | < < < < | | < < < < | | | | | | < < < | | < < < | | | < < | < | | < | < | | < | | | < < < | | | | < < < < < | > | < | > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 | <html><head> <title>thread - Tcl Threading</title> <style type="text/css"><!-- HTML { background: #FFFFFF; color: black; } BODY { background: #FFFFFF; color: black; } DIV.doctools { margin-left: 10%; margin-right: 10%; } DIV.doctools H1,DIV.doctools H2 { margin-left: -5%; } H1, H2, H3, H4 { margin-top: 1em; font-family: sans-serif; font-size: large; color: #005A9C; background: transparent; text-align: left; } H1.doctools_title { text-align: center; } UL,OL { margin-right: 0em; margin-top: 3pt; margin-bottom: 3pt; } UL LI { list-style: disc; } OL LI { list-style: decimal; } DT { padding-top: 1ex; } UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL { font: normal 12pt/14pt sans-serif; list-style: none; } LI.doctools_section, LI.doctools_subsection { list-style: none; margin-left: 0em; text-indent: 0em; padding: 0em; } PRE { display: block; font-family: monospace; white-space: pre; margin: 0%; padding-top: 0.5ex; padding-bottom: 0.5ex; padding-left: 1ex; padding-right: 1ex; width: 100%; } PRE.doctools_example { color: black; background: #f5dcb3; border: 1px solid black; } UL.doctools_requirements LI, UL.doctools_syntax LI { list-style: none; margin-left: 0em; text-indent: 0em; padding: 0em; } DIV.doctools_synopsis { color: black; background: #80ffff; border: 1px solid black; font-family: serif; margin-top: 1em; margin-bottom: 1em; } UL.doctools_syntax { margin-top: 1em; border-top: 1px solid black; } UL.doctools_requirements { margin-bottom: 1em; border-bottom: 1px solid black; } --></style> </head> <! -- Generated from file '' by tcllib/doctools with format 'html' --> <! -- thread.n --> <body><div class="doctools"> <h1 class="doctools_title">thread(n) 2.8 "Tcl Threading"</h1> <div id="name" class="doctools_section"><h2><a name="name">Name</a></h2> <p>thread - Extension for script access to Tcl threading</p> </div> <div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2> <ul class="doctools_toc"> <li class="doctools_section"><a href="#toc">Table Of Contents</a></li> <li class="doctools_section"><a href="#synopsis">Synopsis</a></li> <li class="doctools_section"><a href="#section1">Description</a></li> <li class="doctools_section"><a href="#section2">COMMANDS</a></li> <li class="doctools_section"><a href="#section3">DISCUSSION</a></li> <li class="doctools_section"><a href="#see-also">See Also</a></li> <li class="doctools_section"><a href="#keywords">Keywords</a></li> </ul> </div> <div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2> <div class="doctools_synopsis"> <ul class="doctools_requirements"> <li>package require <b class="pkgname">Tcl 8.4</b></li> <li>package require <b class="pkgname">Thread <span class="opt">?2.8?</span></b></li> </ul> <ul class="doctools_syntax"> <li><a href="#1"><b class="cmd">thread::create</b> <span class="opt">?-joinable?</span> <span class="opt">?-preserved?</span> <span class="opt">?script?</span></a></li> <li><a href="#2"><b class="cmd">thread::preserve</b> <span class="opt">?id?</span></a></li> <li><a href="#3"><b class="cmd">thread::release</b> <span class="opt">?-wait?</span> <span class="opt">?id?</span></a></li> <li><a href="#4"><b class="cmd">thread::id</b></a></li> <li><a href="#5"><b class="cmd">thread::errorproc</b> <span class="opt">?procname?</span></a></li> <li><a href="#6"><b class="cmd">thread::cancel</b> <span class="opt">?-unwind?</span> <i class="arg">id</i> <span class="opt">?result?</span></a></li> <li><a href="#7"><b class="cmd">thread::unwind</b></a></li> <li><a href="#8"><b class="cmd">thread::exit</b> <span class="opt">?status?</span></a></li> <li><a href="#9"><b class="cmd">thread::names</b></a></li> <li><a href="#10"><b class="cmd">thread::exists</b> <i class="arg">id</i></a></li> <li><a href="#11"><b class="cmd">thread::send</b> <span class="opt">?-async?</span> <span class="opt">?-head?</span> <i class="arg">id</i> <i class="arg">script</i> <span class="opt">?varname?</span></a></li> <li><a href="#12"><b class="cmd">thread::broadcast</b> <i class="arg">script</i></a></li> <li><a href="#13"><b class="cmd">thread::wait</b></a></li> <li><a href="#14"><b class="cmd">thread::eval</b> <span class="opt">?-lock mutex?</span> <i class="arg">arg</i> <span class="opt">?arg ...?</span></a></li> <li><a href="#15"><b class="cmd">thread::join</b> <i class="arg">id</i></a></li> <li><a href="#16"><b class="cmd">thread::configure</b> <i class="arg">id</i> <span class="opt">?option?</span> <span class="opt">?value?</span> <span class="opt">?...?</span></a></li> <li><a href="#17"><b class="cmd">thread::transfer</b> <i class="arg">id</i> <i class="arg">channel</i></a></li> <li><a href="#18"><b class="cmd">thread::detach</b> <i class="arg">channel</i></a></li> <li><a href="#19"><b class="cmd">thread::attach</b> <i class="arg">channel</i></a></li> <li><a href="#20"><b class="cmd">thread::mutex</b></a></li> <li><a href="#21"><b class="cmd">thread::mutex</b> <b class="method">create</b> <span class="opt">?-recursive?</span></a></li> <li><a href="#22"><b class="cmd">thread::mutex</b> <b class="method">destroy</b> <i class="arg">mutex</i></a></li> <li><a href="#23"><b class="cmd">thread::mutex</b> <b class="method">lock</b> <i class="arg">mutex</i></a></li> <li><a href="#24"><b class="cmd">thread::mutex</b> <b class="method">unlock</b> <i class="arg">mutex</i></a></li> <li><a href="#25"><b class="cmd">thread::rwmutex</b></a></li> <li><a href="#26"><b class="cmd">thread::rwmutex</b> <b class="method">create</b></a></li> <li><a href="#27"><b class="cmd">thread::rwmutex</b> <b class="method">destroy</b> <i class="arg">mutex</i></a></li> <li><a href="#28"><b class="cmd">thread::rwmutex</b> <b class="method">rlock</b> <i class="arg">mutex</i></a></li> <li><a href="#29"><b class="cmd">thread::rwmutex</b> <b class="method">wlock</b> <i class="arg">mutex</i></a></li> <li><a href="#30"><b class="cmd">thread::rwmutex</b> <b class="method">unlock</b> <i class="arg">mutex</i></a></li> <li><a href="#31"><b class="cmd">thread::cond</b></a></li> <li><a href="#32"><b class="cmd">thread::cond</b> <b class="method">create</b></a></li> <li><a href="#33"><b class="cmd">thread::cond</b> <b class="method">destroy</b> <i class="arg">cond</i></a></li> <li><a href="#34"><b class="cmd">thread::cond</b> <b class="method">notify</b> <i class="arg">cond</i></a></li> <li><a href="#35"><b class="cmd">thread::cond</b> <b class="method">wait</b> <i class="arg">cond</i> <i class="arg">mutex</i> <span class="opt">?ms?</span></a></li> </ul> </div> </div> <div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2> <p>The <b class="package">thread</b> extension creates threads that contain Tcl interpreters, and it lets you send scripts to those threads for evaluation. Additionaly, it provides script-level access to basic thread synchronization primitives, like mutexes and condition variables.</p> </div> <div id="section2" class="doctools_section"><h2><a name="section2">COMMANDS</a></h2> <p>This section describes commands for creating and destroying threads and sending scripts to threads for evaluation.</p> <dl class="doctools_definitions"> <dt><a name="1"><b class="cmd">thread::create</b> <span class="opt">?-joinable?</span> <span class="opt">?-preserved?</span> <span class="opt">?script?</span></a></dt> <dd><p>This command creates a thread that contains a Tcl interpreter. The Tcl interpreter either evaluates the optional <b class="option">script</b>, if specified, or it waits in the event loop for scripts that arrive via the <b class="cmd">thread::send</b> command. The result, if any, of the optional <b class="option">script</b> is never returned to the caller. The result of <b class="cmd">thread::create</b> is the ID of the thread. This is the opaque handle which identifies the newly created thread for all other package commands. The handle of the thread goes out of scope automatically when thread is marked for exit (see the <b class="cmd">thread::release</b> command below).</p> <p>If the optional <b class="option">script</b> argument contains the <b class="cmd">thread::wait</b> command the thread will enter into the event loop. If such command is not found in the <b class="option">script</b> the thread will run the <b class="option">script</b> to the end and exit. In that case, the handle may be safely ignored since it refers to a thread which does not exists any more at the time when the command returns.</p> <p>Using flag <b class="option">-joinable</b> it is possible to create a joinable thread, i.e. one upon whose exit can be waited upon by using <b class="cmd">thread::join</b> command. Note that failure to join a thread created with <b class="option">-joinable</b> flag results in resource and memory leaks.</p> <p>Threads created by the <b class="cmd">thread::create</b> cannot be destroyed forcefully. Consequently, there is no corresponding thread destroy command. A thread may only be released using the <b class="cmd">thread::release</b> and if its internal reference count drops to zero, the thread is marked for exit. This kicks the thread out of the event loop servicing and the thread continues to execute commands passed in the <b class="option">script</b> argument, following the <b class="cmd">thread::wait</b> command. If this was the last command in the script, as usualy the case, the thread will exit.</p> <p>It is possible to create a situation in which it may be impossible to terminate the thread, for example by putting some endless loop after the <b class="cmd">thread::wait</b> or entering the event loop again by doing an vwait-type of command. In such cases, the thread may never exit. This is considered to be a bad practice and should be avoided if possible. This is best illustrated by the example below:</p> <pre class="doctools_example"> # You should never do ... set tid [thread::create { package require Http thread::wait vwait forever ; # <-- this! }] </pre> <p>The thread created in the above example will never be able to exit. After it has been released with the last matching <b class="cmd">thread::release</b> call, the thread will jump out of the <b class="cmd">thread::wait</b> and continue to execute commands following. It will enter <b class="cmd">vwait</b> command and wait endlessly for events. There is no way one can terminate such thread, so you wouldn't want to do this!</p> <p>Each newly created has its internal reference counter set to 0 (zero), i.e. it is unreserved. This counter gets incremented by a call to <b class="cmd">thread::preserve</b> and decremented by a call to <b class="cmd">thread::release</b> command. These two commands implement simple but effective thread reservation system and offer predictable and controllable thread termination capabilities. It is however possible to create initialy preserved threads by using flag <b class="option">-preserved</b> of the <b class="cmd">thread::create</b> command. Threads created with this flag have the initial value of the reference counter of 1 (one), and are thus initially marked reserved.</p></dd> <dt><a name="2"><b class="cmd">thread::preserve</b> <span class="opt">?id?</span></a></dt> <dd><p>This command increments the thread reference counter. Each call to this command increments the reference counter by one (1). Command returns the value of the reference counter after the increment. If called with the optional thread <b class="option">id</b>, the command preserves the given thread. Otherwise the current thread is preserved.</p> <p>With reference counting, one can implement controlled access to a shared Tcl thread. By incrementing the reference counter, the caller signalizes that he/she wishes to use the thread for a longer period of time. By decrementing the counter, caller signalizes that he/she has finished using the thread.</p></dd> <dt><a name="3"><b class="cmd">thread::release</b> <span class="opt">?-wait?</span> <span class="opt">?id?</span></a></dt> <dd><p>This command decrements the thread reference counter. Each call to this command decrements the reference counter by one (1). If called with the optional thread <b class="option">id</b>, the command releases the given thread. Otherwise, the current thread is released. Command returns the value of the reference counter after the decrement. When the reference counter reaches zero (0), the target thread is marked for termination. You should not reference the thread after the <b class="cmd">thread::release</b> command returns zero or negative integer. The handle of the thread goes out of scope and should not be used any more. Any following reference to the same thread handle will result in Tcl error.</p> <p>Optional flag <b class="option">-wait</b> instructs the caller thread to wait for the target thread to exit, if the effect of the command would result in termination of the target thread, i.e. if the return result would be zero (0). Without the flag, the caller thread does not wait for the target thread to exit. Care must be taken when using the <b class="option">-wait</b>, since this may block the caller thread indefinitely. This option has been implemented for some special uses of the extension and is deprecated for regular use. Regular users should create joinable threads by using the <b class="option">-joinable</b> option of the <b class="cmd">thread::create</b> command and the <b class="cmd">thread::join</b> to wait for thread to exit.</p></dd> <dt><a name="4"><b class="cmd">thread::id</b></a></dt> <dd><p>This command returns the ID of the current thread.</p></dd> <dt><a name="5"><b class="cmd">thread::errorproc</b> <span class="opt">?procname?</span></a></dt> <dd><p>This command sets a handler for errors that occur in scripts sent asynchronously, using the <b class="option">-async</b> flag of the <b class="cmd">thread::send</b> command, to other threads. If no handler is specified, the current handler is returned. The empty string resets the handler to default (unspecified) value. An uncaught error in a thread causes an error message to be sent to the standard error channel. This default reporting scheme can be changed by registering a procedure which is called to report the error. The <i class="arg">procname</i> is called in the interpreter that invoked the <b class="cmd">thread::errorproc</b> command. The <i class="arg">procname</i> is called like this:</p> <pre class="doctools_example"> myerrorproc thread_id errorInfo </pre> </dd> <dt><a name="6"><b class="cmd">thread::cancel</b> <span class="opt">?-unwind?</span> <i class="arg">id</i> <span class="opt">?result?</span></a></dt> <dd><p>This command requires Tcl version 8.6 or higher.</p> <p>Cancels the script being evaluated in the thread given by the <i class="arg">id</i> parameter. Without the <b class="option">-unwind</b> switch the evaluation stack for the interpreter is unwound until an enclosing catch command is found or there are no further invocations of the interpreter left on the call stack. With the <b class="option">-unwind</b> switch the evaluation stack for the interpreter is unwound without regard to any intervening catch command until there are no further invocations of the interpreter left on the call stack. If <i class="arg">result</i> is present, it will be used as the error message string; otherwise, a default error message string will be used.</p></dd> <dt><a name="7"><b class="cmd">thread::unwind</b></a></dt> <dd><p>Use of this command is deprecated in favour of more advanced thread reservation system implemented with <b class="cmd">thread::preserve</b> and <b class="cmd">thread::release</b> commands. Support for <b class="cmd">thread::unwind</b> command will dissapear in some future major release of the extension.</p> <p>This command stops a prior <b class="cmd">thread::wait</b> command. Execution of the script passed to newly created thread will continue from the <b class="cmd">thread::wait</b> command. If <b class="cmd">thread::wait</b> was the last command in the script, the thread will exit. The command returns empty result but may trigger Tcl error with the message "target thread died" in some situations.</p></dd> <dt><a name="8"><b class="cmd">thread::exit</b> <span class="opt">?status?</span></a></dt> <dd><p>Use of this command is deprecated in favour of more advanced thread reservation system implemented with <b class="cmd">thread::preserve</b> and <b class="cmd">thread::release</b> commands. Support for <b class="cmd">thread::exit</b> command will dissapear in some future major release of the extension.</p> <p>This command forces a thread stuck in the <b class="cmd">thread::wait</b> command to unconditionaly exit. The thread's exit status defaults to 666 and can be specified using the optional <i class="arg">status</i> argument. The execution of <b class="cmd">thread::exit</b> command is guaranteed to leave the program memory in the unconsistent state, produce memory leaks and otherwise affect other subsytem(s) of the Tcl application in an unpredictable manner. The command returns empty result but may trigger Tcl error with the message "target thread died" in some situations.</p></dd> <dt><a name="9"><b class="cmd">thread::names</b></a></dt> <dd><p>This command returns a list of thread IDs. These are only for threads that have been created via <b class="cmd">thread::create</b> command. If your application creates other threads at the C level, they are not reported by this command.</p></dd> <dt><a name="10"><b class="cmd">thread::exists</b> <i class="arg">id</i></a></dt> <dd><p>Returns true (1) if thread given by the <i class="arg">id</i> parameter exists, false (0) otherwise. This applies only for threads that have been created via <b class="cmd">thread::create</b> command.</p></dd> <dt><a name="11"><b class="cmd">thread::send</b> <span class="opt">?-async?</span> <span class="opt">?-head?</span> <i class="arg">id</i> <i class="arg">script</i> <span class="opt">?varname?</span></a></dt> <dd><p>This command passes a <i class="arg">script</i> to another thread and, optionally, waits for the result. If the <b class="option">-async</b> flag is specified, the command does not wait for the result and it returns empty string. The target thread must enter it's event loop in order to receive scripts sent via this command. This is done by default for threads created without a startup script. Threads can enter the event loop explicitly by calling <b class="cmd">thread::wait</b> or any other relevant Tcl/Tk command, like <b class="cmd">update</b>, <b class="cmd">vwait</b>, etc.</p> <p>Optional <b class="option">varname</b> specifies name of the variable to store the result of the <i class="arg">script</i>. Without the <b class="option">-async</b> flag, the command returns the evaluation code, similarily to the standard Tcl <b class="cmd">catch</b> command. If, however, the <b class="option">-async</b> flag is specified, the command returns immediately and caller can later <b class="cmd">vwait</b> on <span class="opt">?varname?</span> to get the result of the passed <i class="arg">script</i></p> <pre class="doctools_example"> set t1 [thread::create] set t2 [thread::create] thread::send -async $t1 "set a 1" result thread::send -async $t2 "set b 2" result for {set i 0} {$i < 2} {incr i} { vwait result } </pre> <p>In the above example, two threads were fed work and both of them were instructed to signalize the same variable "result" in the calling thread. The caller entered the event loop twice to get both results. Note, however, that the order of the received results may vary, depending on the current system load, type of work done, etc, etc.</p> <p>Many threads can simultaneously send scripts to the target thread for execution. All of them are entered into the event queue of the target thread and executed on the FIFO basis, intermingled with optional other events pending in the event queue of the target thread. Using the optional <span class="opt">?-head?</span> switch, scripts posted to the thread's event queue can be placed on the head, instead on the tail of the queue, thus being executed in the LIFO fashion.</p></dd> <dt><a name="12"><b class="cmd">thread::broadcast</b> <i class="arg">script</i></a></dt> <dd><p>This command passes a <i class="arg">script</i> to all threads created by the package for execution. It does not wait for response from any of the threads.</p></dd> <dt><a name="13"><b class="cmd">thread::wait</b></a></dt> <dd><p>This enters the event loop so a thread can receive messages from the <b class="cmd">thread::send</b> command. This command should only be used within the script passed to the <b class="cmd">thread::create</b>. It should be the very last command in the script. If this is not the case, the exiting thread will continue executing the script lines past the <b class="cmd">thread::wait</b> which is usually not what you want and/or expect.</p> <pre class="doctools_example"> set t1 [thread::create { # # Do some initialization work here # thread::wait ; # Enter the event loop }] </pre> </dd> <dt><a name="14"><b class="cmd">thread::eval</b> <span class="opt">?-lock mutex?</span> <i class="arg">arg</i> <span class="opt">?arg ...?</span></a></dt> <dd><p>This command concatenates passed arguments and evaluates the resulting script under the mutex protection. If no mutex is specified by using the <span class="opt">?-lock mutex?</span> optional argument, the internal static mutex is used.</p></dd> <dt><a name="15"><b class="cmd">thread::join</b> <i class="arg">id</i></a></dt> <dd><p>This command waits for the thread with ID <i class="arg">id</i> to exit and then returns it's exit code. Errors will be returned for threads which are not joinable or already waited upon by another thread. Upon the join the handle of the thread has gone out of scope and should not be used any more.</p></dd> <dt><a name="16"><b class="cmd">thread::configure</b> <i class="arg">id</i> <span class="opt">?option?</span> <span class="opt">?value?</span> <span class="opt">?...?</span></a></dt> <dd><p>This command configures various low-level aspects of the thread with ID <i class="arg">id</i> in the similar way as the standard Tcl command <b class="cmd">fconfigure</b> configures some Tcl channel options. Options currently supported are: <b class="option">-eventmark</b> and <b class="option">-unwindonerror</b>.</p> <p>The <b class="option">-eventmark</b> option, when set, limits the number of asynchronously posted scripts to the thread event loop. The <b class="cmd">thread::send -async</b> command will block until the number of pending scripts in the event loop does not drop below the value configured with <b class="option">-eventmark</b>. Default value for the <b class="option">-eventmark</b> is 0 (zero) which effectively disables the checking, i.e. allows for unlimited number of posted scripts.</p> <p>The <b class="option">-unwindonerror</b> option, when set, causes the target thread to unwind if the result of the script processing resulted in error. Default value for the <b class="option">-unwindonerror</b> is 0 (false), i.e. thread continues to process scripts after one of the posted scripts fails.</p></dd> <dt><a name="17"><b class="cmd">thread::transfer</b> <i class="arg">id</i> <i class="arg">channel</i></a></dt> <dd><p>This moves the specified <i class="arg">channel</i> from the current thread and interpreter to the main interpreter of the thread with the given <i class="arg">id</i>. After the move the current interpreter has no access to the channel any more, but the main interpreter of the target thread will be able to use it from now on. The command waits until the other thread has incorporated the channel. Because of this it is possible to deadlock the participating threads by commanding the other through a synchronous <b class="cmd">thread::send</b> to transfer a channel to us. This easily extends into longer loops of threads waiting for each other. Other restrictions: the channel in question must not be shared among multiple interpreters running in the sending thread. This automatically excludes the special channels for standard input, output and error.</p> <p>Due to the internal Tcl core implementation and the restriction on transferring shared channels, one has to take extra measures when transferring socket channels created by accepting the connection out of the <b class="cmd">socket</b> commands callback procedures:</p> <pre class="doctools_example"> socket -server _Accept 2200 proc _Accept {s ipaddr port} { after idle [list Accept $s $ipaddr $port] } proc Accept {s ipaddr port} { set tid [thread::create] thread::transfer $tid $s } </pre> </dd> <dt><a name="18"><b class="cmd">thread::detach</b> <i class="arg">channel</i></a></dt> <dd><p>This detaches the specified <i class="arg">channel</i> from the current thread and interpreter. After that, the current interpreter has no access to the channel any more. The channel is in the parked state until some other (or the same) thread attaches the channel again with <b class="cmd">thread::attach</b>. Restrictions: same as for transferring shared channels with the <b class="cmd">thread::transfer</b> command.</p></dd> <dt><a name="19"><b class="cmd">thread::attach</b> <i class="arg">channel</i></a></dt> <dd><p>This attaches the previously detached <i class="arg">channel</i> in the current thread/interpreter. For already existing channels, the command does nothing, i.e. it is not an error to attach the same channel more than once. The first operation will actualy perform the operation, while all subsequent operation will just do nothing. Command throws error if the <i class="arg">channel</i> cannot be found in the list of detached channels and/or in the current interpreter.</p></dd> <dt><a name="20"><b class="cmd">thread::mutex</b></a></dt> <dd><p>Mutexes are most common thread synchronization primitives. They are used to synchronize access from two or more threads to one or more shared resources. This command provides script-level access to exclusive and/or recursive mutexes. Exclusive mutexes can be locked only once by one thread, while recursive mutexes can be locked many times by the same thread. For recursive mutexes, number of lock and unlock operations must match, otherwise, the mutex will never be released, which would lead to various deadlock situations.</p> <p>Care has to be taken when using mutexes in an multithreading program. Improper use of mutexes may lead to various deadlock situations, especially when using exclusive mutexes.</p> <p>The <b class="cmd">thread::mutex</b> command supports following subcommands and options:</p> <dl class="doctools_definitions"> <dt><a name="21"><b class="cmd">thread::mutex</b> <b class="method">create</b> <span class="opt">?-recursive?</span></a></dt> <dd><p>Creates the mutex and returns it's opaque handle. This handle should be used for any future reference to the newly created mutex. If no optional <span class="opt">?-recursive?</span> argument was specified, the command creates the exclusive mutex. With the <span class="opt">?-recursive?</span> argument, the command creates a recursive mutex.</p></dd> <dt><a name="22"><b class="cmd">thread::mutex</b> <b class="method">destroy</b> <i class="arg">mutex</i></a></dt> <dd><p>Destroys the <i class="arg">mutex</i>. Mutex should be in unlocked state before the destroy attempt. If the mutex is locked, the command will throw Tcl error.</p></dd> <dt><a name="23"><b class="cmd">thread::mutex</b> <b class="method">lock</b> <i class="arg">mutex</i></a></dt> <dd><p>Locks the <i class="arg">mutex</i>. Locking the exclusive mutex may throw Tcl error if on attempt to lock the same mutex twice from the same thread. If your program logic forces you to lock the same mutex twice or more from the same thread (this may happen in recursive procedure invocations) you should consider using the recursive mutexes.</p></dd> <dt><a name="24"><b class="cmd">thread::mutex</b> <b class="method">unlock</b> <i class="arg">mutex</i></a></dt> <dd><p>Unlocks the <i class="arg">mutex</i> so some other thread may lock it again. Attempt to unlock the already unlocked mutex will throw Tcl error.</p></dd> </dl></dd> <dt><a name="25"><b class="cmd">thread::rwmutex</b></a></dt> <dd><p>This command creates many-readers/single-writer mutexes. Reader/writer mutexes allow you to serialize access to a shared resource more optimally. In situations where a shared resource gets mostly read and seldom modified, you might gain some performace by using reader/writer mutexes instead of exclusive or recursive mutexes.</p> <p>For reading the resource, thread should obtain a read lock on the resource. Read lock is non-exclusive, meaning that more than one thread can obtain a read lock to the same resource, without waiting on other readers. For changing the resource, however, a thread must obtain a exclusive write lock. This lock effectively blocks all threads from gaining the read-lock while the resource is been modified by the writer thread. Only after the write lock has been released, the resource may be read-locked again.</p> <p>The <b class="cmd">thread::rwmutex</b> command supports following subcommands and options:</p> <dl class="doctools_definitions"> <dt><a name="26"><b class="cmd">thread::rwmutex</b> <b class="method">create</b></a></dt> <dd><p>Creates the reader/writer mutex and returns it's opaque handle. This handle should be used for any future reference to the newly created mutex.</p></dd> <dt><a name="27"><b class="cmd">thread::rwmutex</b> <b class="method">destroy</b> <i class="arg">mutex</i></a></dt> <dd><p>Destroys the reader/writer <i class="arg">mutex</i>. If the mutex is already locked, attempt to destroy it will throw Tcl error.</p></dd> <dt><a name="28"><b class="cmd">thread::rwmutex</b> <b class="method">rlock</b> <i class="arg">mutex</i></a></dt> <dd><p>Locks the <i class="arg">mutex</i> for reading. More than one thread may read-lock the same <i class="arg">mutex</i> at the same time.</p></dd> <dt><a name="29"><b class="cmd">thread::rwmutex</b> <b class="method">wlock</b> <i class="arg">mutex</i></a></dt> <dd><p>Locks the <i class="arg">mutex</i> for writing. Only one thread may write-lock the same <i class="arg">mutex</i> at the same time. Attempt to write-lock same <i class="arg">mutex</i> twice from the same thread will throw Tcl error.</p></dd> <dt><a name="30"><b class="cmd">thread::rwmutex</b> <b class="method">unlock</b> <i class="arg">mutex</i></a></dt> <dd><p>Unlocks the <i class="arg">mutex</i> so some other thread may lock it again. Attempt to unlock already unlocked <i class="arg">mutex</i> will throw Tcl error.</p></dd> </dl></dd> <dt><a name="31"><b class="cmd">thread::cond</b></a></dt> <dd><p>This command provides script-level access to condition variables. A condition variable creates a safe environment for the program to test some condition, sleep on it when false and be awakened when it might have become true. A condition variable is always used in the conjuction with an exclusive mutex. If you attempt to use other type of mutex in conjuction with the condition variable, a Tcl error will be thrown.</p> <p>The command supports following subcommands and options:</p> <dl class="doctools_definitions"> <dt><a name="32"><b class="cmd">thread::cond</b> <b class="method">create</b></a></dt> <dd><p>Creates the condition variable and returns it's opaque handle. This handle should be used for any future reference to newly created condition variable.</p></dd> <dt><a name="33"><b class="cmd">thread::cond</b> <b class="method">destroy</b> <i class="arg">cond</i></a></dt> <dd><p>Destroys condition variable <i class="arg">cond</i>. Extreme care has to be taken that nobody is using (i.e. waiting on) the condition variable, otherwise unexpected errors may happen.</p></dd> <dt><a name="34"><b class="cmd">thread::cond</b> <b class="method">notify</b> <i class="arg">cond</i></a></dt> <dd><p>Wakes up all threads waiting on the condition variable <i class="arg">cond</i>.</p></dd> <dt><a name="35"><b class="cmd">thread::cond</b> <b class="method">wait</b> <i class="arg">cond</i> <i class="arg">mutex</i> <span class="opt">?ms?</span></a></dt> <dd><p>This command is used to suspend program execution until the condition variable <i class="arg">cond</i> has been signalled or the optional timer has expired. The exclusive <i class="arg">mutex</i> must be locked by the calling thread on entrance to this command. If the mutex is not locked, Tcl error is thrown. While waiting on the <i class="arg">cond</i>, the command releases <i class="arg">mutex</i>. Before returning to the calling thread, the command re-acquires the <i class="arg">mutex</i> again. Unlocking the <i class="arg">mutex</i> and waiting on the condition variable <i class="arg">cond</i> is done atomically.</p> <p>The <b class="option">ms</b> command option, if given, must be an integer specifying time interval in milliseconds the command waits to be signalled. Otherwise the command waits on condition notify forever.</p> <p>In multithreading programs, there are many situations where a thread has to wait for some event to happen until it is allowed to proceed. This is usually accomplished by repeatedly testing a condition under the mutex protection and waiting on the condition variable until the condition evaluates to true:</p> <pre class="doctools_example"> set mutex [thread::mutex create] set cond [thread::cond create] thread::mutex lock $mutex while {<some_condition_is_true>} { thread::cond wait $cond $mutex } # Do some work under mutex protection thread::mutex unlock $mutex </pre> <p>Repeated testing of the condition is needed since the condition variable may get signalled without the condition being actually changed (spurious thread wake-ups, for example).</p></dd> </dl></dd> </dl> </div> <div id="section3" class="doctools_section"><h2><a name="section3">DISCUSSION</a></h2> <p>The fundamental threading model in Tcl is that there can be one or more Tcl interpreters per thread, but each Tcl interpreter should only be used by a single thread which created it. A "shared memory" abstraction is awkward to provide in Tcl because Tcl makes assumptions about variable and data ownership. Therefore this extension supports a simple form of threading where the main thread can manage several background, or "worker" threads. For example, an event-driven server can pass requests to worker threads, and then await responses from worker threads or new client requests. Everything goes through the common Tcl event loop, so message passing between threads works naturally with event-driven I/O, <b class="cmd">vwait</b> on variables, and so forth. For the transfer of bulk information it is possible to move channels between the threads.</p> <p>For advanced multithreading scripts, script-level access to two basic synchronization primitives, mutex and condition variables, is also supported.</p> </div> <div id="see-also" class="doctools_section"><h2><a name="see-also">See Also</a></h2> <p><a href="http://www.tcl.tk/doc/howto/thread_model.html">http://www.tcl.tk/doc/howto/thread_model.html</a>, tpool, tsv, ttrace</p> </div> <div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2> <p>events, message passing, mutex, synchronization, thread</p> </div> </div></body></html> |
Changes to doc/html/tpool.html.
|
| | < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | | | < < | | | | | | > > > > > > > > > | < < < < < < < < < < | | > > | | | | | | | | > > | < | > > | | | < < | < | < | < | | < | | < < | < | | | | < < | | | < < < | | | | < | | | | < < < | | | | < < < | | < | < < < | < < | | | | < < | < < | | < | | | | < | | | < < < < | | | < | | | | | < < < < | | | | | | < < < < | | | | | | < < | < < | | | | < < < < | | | | | | > > > > > > > > > > > > > | | < < < | | < | | | | < < < < < | > | < | > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | <html><head> <title>tpool - Tcl Threading</title> <style type="text/css"><!-- HTML { background: #FFFFFF; color: black; } BODY { background: #FFFFFF; color: black; } DIV.doctools { margin-left: 10%; margin-right: 10%; } DIV.doctools H1,DIV.doctools H2 { margin-left: -5%; } H1, H2, H3, H4 { margin-top: 1em; font-family: sans-serif; font-size: large; color: #005A9C; background: transparent; text-align: left; } H1.doctools_title { text-align: center; } UL,OL { margin-right: 0em; margin-top: 3pt; margin-bottom: 3pt; } UL LI { list-style: disc; } OL LI { list-style: decimal; } DT { padding-top: 1ex; } UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL { font: normal 12pt/14pt sans-serif; list-style: none; } LI.doctools_section, LI.doctools_subsection { list-style: none; margin-left: 0em; text-indent: 0em; padding: 0em; } PRE { display: block; font-family: monospace; white-space: pre; margin: 0%; padding-top: 0.5ex; padding-bottom: 0.5ex; padding-left: 1ex; padding-right: 1ex; width: 100%; } PRE.doctools_example { color: black; background: #f5dcb3; border: 1px solid black; } UL.doctools_requirements LI, UL.doctools_syntax LI { list-style: none; margin-left: 0em; text-indent: 0em; padding: 0em; } DIV.doctools_synopsis { color: black; background: #80ffff; border: 1px solid black; font-family: serif; margin-top: 1em; margin-bottom: 1em; } UL.doctools_syntax { margin-top: 1em; border-top: 1px solid black; } UL.doctools_requirements { margin-bottom: 1em; border-bottom: 1px solid black; } --></style> </head> <! -- Generated from file '' by tcllib/doctools with format 'html' --> <! -- tpool.n --> <body><div class="doctools"> <h1 class="doctools_title">tpool(n) 2.8 "Tcl Threading"</h1> <div id="name" class="doctools_section"><h2><a name="name">Name</a></h2> <p>tpool - Part of the Tcl threading extension implementing pools of worker threads.</p> </div> <div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2> <ul class="doctools_toc"> <li class="doctools_section"><a href="#toc">Table Of Contents</a></li> <li class="doctools_section"><a href="#synopsis">Synopsis</a></li> <li class="doctools_section"><a href="#section1">Description</a></li> <li class="doctools_section"><a href="#section2">COMMANDS</a></li> <li class="doctools_section"><a href="#section3">DISCUSSION</a></li> <li class="doctools_section"><a href="#see-also">See Also</a></li> <li class="doctools_section"><a href="#keywords">Keywords</a></li> </ul> </div> <div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2> <div class="doctools_synopsis"> <ul class="doctools_requirements"> <li>package require <b class="pkgname">Tcl 8.4</b></li> <li>package require <b class="pkgname">Thread <span class="opt">?2.8?</span></b></li> </ul> <ul class="doctools_syntax"> <li><a href="#1"><b class="cmd">tpool::create</b> <span class="opt">?options?</span></a></li> <li><a href="#2"><b class="cmd">tpool::names</b></a></li> <li><a href="#3"><b class="cmd">tpool::post</b> <span class="opt">?-detached?</span> <span class="opt">?-nowait?</span> <i class="arg">tpool</i> <i class="arg">script</i></a></li> <li><a href="#4"><b class="cmd">tpool::wait</b> <i class="arg">tpool</i> <i class="arg">joblist</i> <span class="opt">?varname?</span></a></li> <li><a href="#5"><b class="cmd">tpool::cancel</b> <i class="arg">tpool</i> <i class="arg">joblist</i> <span class="opt">?varname?</span></a></li> <li><a href="#6"><b class="cmd">tpool::get</b> <i class="arg">tpool</i> <i class="arg">job</i></a></li> <li><a href="#7"><b class="cmd">tpool::preserve</b> <i class="arg">tpool</i></a></li> <li><a href="#8"><b class="cmd">tpool::release</b> <i class="arg">tpool</i></a></li> <li><a href="#9"><b class="cmd">tpool::suspend</b> <i class="arg">tpool</i></a></li> <li><a href="#10"><b class="cmd">tpool::resume</b> <i class="arg">tpool</i></a></li> </ul> </div> </div> <div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2> <p>This package creates and manages pools of worker threads. It allows you to post jobs to worker threads and wait for their completion. The threadpool implementation is Tcl event-loop aware. That means that any time a caller is forced to wait for an event (job being completed or a worker thread becoming idle or initialized), the implementation will enter the event loop and allow for servicing of other pending file or timer (or any other supported) events.</p> </div> <div id="section2" class="doctools_section"><h2><a name="section2">COMMANDS</a></h2> <dl class="doctools_definitions"> <dt><a name="1"><b class="cmd">tpool::create</b> <span class="opt">?options?</span></a></dt> <dd><p>This command creates new threadpool. It accepts several options as key-value pairs. Options are used to tune some threadpool parameters. The command returns the ID of the newly created threadpool.</p> <p>Following options are supported:</p> <dl class="doctools_options"> <dt><b class="option">-minworkers</b> <i class="arg">number</i></dt> <dd><p>Minimum number of worker threads needed for this threadpool instance. During threadpool creation, the implementation will create somany worker threads upfront and will keep at least number of them alive during the lifetime of the threadpool instance. Default value of this parameter is 0 (zero). which means that a newly threadpool will have no worker threads initialy. All worker threads will be started on demand by callers running <b class="cmd">tpool::post</b> command and posting jobs to the job queue.</p></dd> <dt><b class="option">-maxworkers</b> <i class="arg">number</i></dt> <dd><p>Maximum number of worker threads allowed for this threadpool instance. If a new job is pending and there are no idle worker threads available, the implementation will try to create new worker thread. If the number of available worker threads is lower than the given number, new worker thread will start. The caller will automatically enter the event loop and wait until the worker thread has initialized. If. however, the number of available worker threads is equal to the given number, the caller will enter the event loop and wait for the first worker thread to get idle, thus ready to run the job. Default value of this parameter is 4 (four), which means that the threadpool instance will allow maximum of 4 worker threads running jobs or being idle waiting for new jobs to get posted to the job queue.</p></dd> <dt><b class="option">-idletime</b> <i class="arg">seconds</i></dt> <dd><p>Time in seconds an idle worker thread waits for the job to get posted to the job queue. If no job arrives during this interval and the time expires, the worker thread will check the number of currently available worker threads and if the number is higher than the number set by the <b class="option">minthreads</b> option, it will exit. If an <b class="option">exitscript</b> has been defined, the exiting worker thread will first run the script and then exit. Errors from the exit script, if any, are ignored.</p> <p>The idle worker thread is not servicing the event loop. If you, however, put the worker thread into the event loop, by evaluating the <b class="cmd">vwait</b> or other related Tcl commands, the worker thread will not be in the idle state, hence the idle timer will not be taken into account. Default value for this option is unspecified.</p></dd> <dt><b class="option">-initcmd</b> <i class="arg">script</i></dt> <dd><p>Sets a Tcl script used to initialize new worker thread. This is usually used to load packages and commands in the worker, set default variables, create namespaces, and such. If the passed script runs into a Tcl error, the worker will not be created and the initiating command (either the <b class="cmd">tpool::create</b> or <b class="cmd">tpool::post</b>) will throw error. Default value for this option is unspecified, hence, the Tcl interpreter of the worker thread will contain just the initial set of Tcl commands.</p></dd> <dt><b class="option">-exitcmd</b> <i class="arg">script</i></dt> <dd><p>Sets a Tcl script run when the idle worker thread exits. This is normaly used to cleanup the state of the worker thread, release reserved resources, cleanup memory and such. Default value for this option is unspecified, thus no Tcl script will run on the worker thread exit.</p></dd> </dl></dd> <dt><a name="2"><b class="cmd">tpool::names</b></a></dt> <dd><p>This command returns a list of IDs of threadpools created with the <b class="cmd">tpool::create</b> command. If no threadpools were found, the command will return empty list.</p></dd> <dt><a name="3"><b class="cmd">tpool::post</b> <span class="opt">?-detached?</span> <span class="opt">?-nowait?</span> <i class="arg">tpool</i> <i class="arg">script</i></a></dt> <dd><p>This command sends a <i class="arg">script</i> to the target <i class="arg">tpool</i> threadpool for execution. The script will be executed in the first available idle worker thread. If there are no idle worker threads available, the command will create new one, enter the event loop and service events until the newly created thread is initialized. If the current number of worker threads is equal to the maximum number of worker threads, as defined during the threadpool creation, the command will enter the event loop and service events while waiting for one of the worker threads to become idle. If the optional <span class="opt">?-nowait?</span> argument is given, the command will not wait for one idle worker. It will just place the job in the pool's job queue and return immediately.</p> <p>The command returns the ID of the posted job. This ID is used for subsequent <b class="cmd">tpool::wait</b>, <b class="cmd">tpool::get</b> and <b class="cmd">tpool::cancel</b> commands to wait for and retrieve result of the posted script, or cancel the posted job respectively. If the optional <span class="opt">?-detached?</span> argument is specified, the command will post a detached job. A detached job can not be cancelled or waited upon and is not identified by the job ID.</p> <p>If the threadpool <i class="arg">tpool</i> is not found in the list of active thread pools, the command will throw error. The error will also be triggered if the newly created worker thread fails to initialize.</p></dd> <dt><a name="4"><b class="cmd">tpool::wait</b> <i class="arg">tpool</i> <i class="arg">joblist</i> <span class="opt">?varname?</span></a></dt> <dd><p>This command waits for one or many jobs, whose job IDs are given in the <i class="arg">joblist</i> to get processed by the worker thread(s). If none of the specified jobs are ready, the command will enter the event loop, service events and wait for the first job to get ready.</p> <p>The command returns the list of completed job IDs. If the optional variable <span class="opt">?varname?</span> is given, it will be set to the list of jobs in the <i class="arg">joblist</i> which are still pending. If the threadpool <i class="arg">tpool</i> is not found in the list of active thread pools, the command will throw error.</p></dd> <dt><a name="5"><b class="cmd">tpool::cancel</b> <i class="arg">tpool</i> <i class="arg">joblist</i> <span class="opt">?varname?</span></a></dt> <dd><p>This command cancels the previously posted jobs given by the <i class="arg">joblist</i> to the pool <i class="arg">tpool</i>. Job cancellation succeeds only for job still waiting to be processed. If the job is already being executed by one of the worker threads, the job will not be cancelled. The command returns the list of cancelled job IDs. If the optional variable <span class="opt">?varname?</span> is given, it will be set to the list of jobs in the <i class="arg">joblist</i> which were not cancelled. If the threadpool <i class="arg">tpool</i> is not found in the list of active thread pools, the command will throw error.</p></dd> <dt><a name="6"><b class="cmd">tpool::get</b> <i class="arg">tpool</i> <i class="arg">job</i></a></dt> <dd><p>This command retrieves the result of the previously posted <i class="arg">job</i>. Only results of jobs waited upon with the <b class="cmd">tpool::wait</b> command can be retrieved. If the execution of the script resulted in error, the command will throw the error and update the <b class="variable">errorInfo</b> and <b class="variable">errorCode</b> variables correspondingly. If the pool <i class="arg">tpool</i> is not found in the list of threadpools, the command will throw error. If the job <i class="arg">job</i> is not ready for retrieval, because it is currently being executed by the worker thread, the command will throw error.</p></dd> <dt><a name="7"><b class="cmd">tpool::preserve</b> <i class="arg">tpool</i></a></dt> <dd><p>Each call to this command increments the reference counter of the threadpool <i class="arg">tpool</i> by one (1). Command returns the value of the reference counter after the increment. By incrementing the reference counter, the caller signalizes that he/she wishes to use the resource for a longer period of time.</p></dd> <dt><a name="8"><b class="cmd">tpool::release</b> <i class="arg">tpool</i></a></dt> <dd><p>Each call to this command decrements the reference counter of the threadpool <i class="arg">tpool</i> by one (1).Command returns the value of the reference counter after the decrement. When the reference counter reaches zero (0), the threadpool <i class="arg">tpool</i> is marked for termination. You should not reference the threadpool after the <b class="cmd">tpool::release</b> command returns zero. The <i class="arg">tpool</i> handle goes out of scope and should not be used any more. Any following reference to the same threadpool handle will result in Tcl error.</p></dd> <dt><a name="9"><b class="cmd">tpool::suspend</b> <i class="arg">tpool</i></a></dt> <dd><p>Suspends processing work on this queue. All pool workers are paused but additional work can be added to the pool. Note that adding the additional work will not increase the number of workers dynamically as the pool processing is suspended. Number of workers is maintained to the count that was found prior suspending worker activity. If you need to assure certain number of worker threads, use the <b class="option">minworkers</b> option of the <b class="cmd">tpool::create</b> command.</p></dd> <dt><a name="10"><b class="cmd">tpool::resume</b> <i class="arg">tpool</i></a></dt> <dd><p>Resume processing work on this queue. All paused (suspended) workers are free to get work from the pool. Note that resuming pool operation will just let already created workers to proceed. It will not create additional worker threads to handle the work posted to the pool's work queue.</p></dd> </dl> </div> <div id="section3" class="doctools_section"><h2><a name="section3">DISCUSSION</a></h2> <p>Threadpool is one of the most common threading paradigm when it comes to server applications handling a large number of relatively small tasks. A very simplistic model for building a server application would be to create a new thread each time a request arrives and service the request in the new thread. One of the disadvantages of this approach is that the overhead of creating a new thread for each request is significant; a server that created a new thread for each request would spend more time and consume more system resources in creating and destroying threads than in processing actual user requests. In addition to the overhead of creating and destroying threads, active threads consume system resources. Creating too many threads can cause the system to run out of memory or trash due to excessive memory consumption.</p> <p>A thread pool offers a solution to both the problem of thread life-cycle overhead and the problem of resource trashing. By reusing threads for multiple tasks, the thread-creation overhead is spread over many tasks. As a bonus, because the thread already exists when a request arrives, the delay introduced by thread creation is eliminated. Thus, the request can be serviced immediately. Furthermore, by properly tuning the number of threads in the thread pool, resource thrashing may also be eliminated by forcing any request to wait until a thread is available to process it.</p> </div> <div id="see-also" class="doctools_section"><h2><a name="see-also">See Also</a></h2> <p>thread, tsv, ttrace</p> </div> <div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2> <p>thread, threadpool</p> </div> </div></body></html> |
Changes to doc/html/tsv.html.
|
| | < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | | | < < | < | | | | | | < < < < | | | | | | | | > > | < > > | | > > | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | < | > > | | < | | | | < | < | < < < | | | < < < < | | | | < | | < < | < | | | | < < < < | | | | | < < < < | | | < < < < | | | < < < < | | | < < | < < | | | < < < < | | | | < < < < | | | | < < < < | | | < | | > > > | < < | | | | < | < < < | | | | < < < < | | | | < < < < | | | | | < < < < | | | | < < < < | | | | < < < < | | | | < < < < | | | < < < < | | | < < < < | | < < < | | < | | | | < | < < | | | | | | < | | < | < | < | | < < < < | | < < < < | < < < | < | | < < < < | | | < < < | | < | | < | < | < < | < | | < < | | < < | | < | | | < | < | | | < | < | | | < | < < < | | | | < < < < | | | | < | | | | | | | | < < < | | | | < < < < | | | | | < | | < < | | < | | | | < | | | | < < < < < | > | < | > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | <html><head> <title>tsv - Tcl Threading</title> <style type="text/css"><!-- HTML { background: #FFFFFF; color: black; } BODY { background: #FFFFFF; color: black; } DIV.doctools { margin-left: 10%; margin-right: 10%; } DIV.doctools H1,DIV.doctools H2 { margin-left: -5%; } H1, H2, H3, H4 { margin-top: 1em; font-family: sans-serif; font-size: large; color: #005A9C; background: transparent; text-align: left; } H1.doctools_title { text-align: center; } UL,OL { margin-right: 0em; margin-top: 3pt; margin-bottom: 3pt; } UL LI { list-style: disc; } OL LI { list-style: decimal; } DT { padding-top: 1ex; } UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL { font: normal 12pt/14pt sans-serif; list-style: none; } LI.doctools_section, LI.doctools_subsection { list-style: none; margin-left: 0em; text-indent: 0em; padding: 0em; } PRE { display: block; font-family: monospace; white-space: pre; margin: 0%; padding-top: 0.5ex; padding-bottom: 0.5ex; padding-left: 1ex; padding-right: 1ex; width: 100%; } PRE.doctools_example { color: black; background: #f5dcb3; border: 1px solid black; } UL.doctools_requirements LI, UL.doctools_syntax LI { list-style: none; margin-left: 0em; text-indent: 0em; padding: 0em; } DIV.doctools_synopsis { color: black; background: #80ffff; border: 1px solid black; font-family: serif; margin-top: 1em; margin-bottom: 1em; } UL.doctools_syntax { margin-top: 1em; border-top: 1px solid black; } UL.doctools_requirements { margin-bottom: 1em; border-bottom: 1px solid black; } --></style> </head> <! -- Generated from file '' by tcllib/doctools with format 'html' --> <! -- tsv.n --> <body><div class="doctools"> <h1 class="doctools_title">tsv(n) 2.8 "Tcl Threading"</h1> <div id="name" class="doctools_section"><h2><a name="name">Name</a></h2> <p>tsv - Part of the Tcl threading extension allowing script level manipulation of data shared between threads.</p> </div> <div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2> <ul class="doctools_toc"> <li class="doctools_section"><a href="#toc">Table Of Contents</a></li> <li class="doctools_section"><a href="#synopsis">Synopsis</a></li> <li class="doctools_section"><a href="#section1">Description</a></li> <li class="doctools_section"><a href="#section2">ELEMENT COMMANDS</a></li> <li class="doctools_section"><a href="#section3">LIST COMMANDS</a></li> <li class="doctools_section"><a href="#section4">ARRAY COMMANDS</a></li> <li class="doctools_section"><a href="#section5">KEYED LIST COMMANDS</a></li> <li class="doctools_section"><a href="#section6">DISCUSSION</a></li> <li class="doctools_section"><a href="#section7">CREDITS</a></li> <li class="doctools_section"><a href="#see-also">See Also</a></li> <li class="doctools_section"><a href="#keywords">Keywords</a></li> </ul> </div> <div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2> <div class="doctools_synopsis"> <ul class="doctools_requirements"> <li>package require <b class="pkgname">Tcl 8.4</b></li> <li>package require <b class="pkgname">Thread <span class="opt">?2.8?</span></b></li> </ul> <ul class="doctools_syntax"> <li><a href="#1"><b class="cmd">tsv::names</b> <span class="opt">?pattern?</span></a></li> <li><a href="#2"><b class="cmd">tsv::object</b> <i class="arg">varname</i> <i class="arg">element</i></a></li> <li><a href="#3"><b class="cmd">tsv::set</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?value?</span></a></li> <li><a href="#4"><b class="cmd">tsv::get</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?namedvar?</span></a></li> <li><a href="#5"><b class="cmd">tsv::unset</b> <i class="arg">varname</i> <span class="opt">?element?</span></a></li> <li><a href="#6"><b class="cmd">tsv::exists</b> <i class="arg">varname</i> <i class="arg">element</i></a></li> <li><a href="#7"><b class="cmd">tsv::pop</b> <i class="arg">varname</i> <i class="arg">element</i></a></li> <li><a href="#8"><b class="cmd">tsv::move</b> <i class="arg">varname</i> <i class="arg">oldname</i> <i class="arg">newname</i></a></li> <li><a href="#9"><b class="cmd">tsv::incr</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?count?</span></a></li> <li><a href="#10"><b class="cmd">tsv::append</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">value</i> <span class="opt">?value ...?</span></a></li> <li><a href="#11"><b class="cmd">tsv::lock</b> <i class="arg">varname</i> <i class="arg">arg</i> <span class="opt">?arg ...?</span></a></li> <li><a href="#12"><b class="cmd">tsv::handlers</b></a></li> <li><a href="#13"><b class="cmd">tsv::lappend</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">value</i> <span class="opt">?value ...?</span></a></li> <li><a href="#14"><b class="cmd">tsv::linsert</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">index</i> <i class="arg">value</i> <span class="opt">?value ...?</span></a></li> <li><a href="#15"><b class="cmd">tsv::lreplace</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">first</i> <i class="arg">last</i> <span class="opt">?value ...?</span></a></li> <li><a href="#16"><b class="cmd">tsv::llength</b> <i class="arg">varname</i> <i class="arg">element</i></a></li> <li><a href="#17"><b class="cmd">tsv::lindex</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?index?</span></a></li> <li><a href="#18"><b class="cmd">tsv::lrange</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">from</i> <i class="arg">to</i></a></li> <li><a href="#19"><b class="cmd">tsv::lsearch</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?options?</span> <i class="arg">pattern</i></a></li> <li><a href="#20"><b class="cmd">tsv::lset</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">index</i> <span class="opt">?index ...?</span> <i class="arg">value</i></a></li> <li><a href="#21"><b class="cmd">tsv::lpop</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?index?</span></a></li> <li><a href="#22"><b class="cmd">tsv::lpush</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?index?</span></a></li> <li><a href="#23"><b class="cmd">tsv::array set</b> <i class="arg">varname</i> <i class="arg">list</i></a></li> <li><a href="#24"><b class="cmd">tsv::array get</b> <i class="arg">varname</i> <span class="opt">?pattern?</span></a></li> <li><a href="#25"><b class="cmd">tsv::array names</b> <i class="arg">varname</i> <span class="opt">?pattern?</span></a></li> <li><a href="#26"><b class="cmd">tsv::array size</b> <i class="arg">varname</i></a></li> <li><a href="#27"><b class="cmd">tsv::array reset</b> <i class="arg">varname</i> <i class="arg">list</i></a></li> <li><a href="#28"><b class="cmd">tsv::array bind</b> <i class="arg">varname</i> <i class="arg">handle</i></a></li> <li><a href="#29"><b class="cmd">tsv::array unbind</b> <i class="arg">varname</i></a></li> <li><a href="#30"><b class="cmd">tsv::array isbound</b> <i class="arg">varname</i></a></li> <li><a href="#31"><b class="cmd">tsv::keyldel</b> <i class="arg">varname</i> <i class="arg">keylist</i> <i class="arg">key</i></a></li> <li><a href="#32"><b class="cmd">tsv::keylget</b> <i class="arg">varname</i> <i class="arg">keylist</i> <i class="arg">key</i> <span class="opt">?retvar?</span></a></li> <li><a href="#33"><b class="cmd">tsv::keylkeys</b> <i class="arg">varname</i> <i class="arg">keylist</i> <span class="opt">?key?</span></a></li> <li><a href="#34"><b class="cmd">tsv::keylset</b> <i class="arg">varname</i> <i class="arg">keylist</i> <i class="arg">key</i> <i class="arg">value</i> <span class="opt">?key value..?</span></a></li> </ul> </div> </div> <div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2> <p>This section describes commands implementing thread shared variables. A thread shared variable is very similar to a Tcl array but in contrast to a Tcl array it is created in shared memory and can be accessed from many threads at the same time. Important feature of thread shared variable is that each access to the variable is internaly protected by a mutex so script programmer does not have to take care about locking the variable himself.</p> <p>Thread shared variables are not bound to any thread explicitly. That means that when a thread which created any of thread shared variables exits, the variable and associated memory is not unset/reclaimed. User has to explicitly unset the variable to reclaim the memory consumed by the variable.</p> </div> <div id="section2" class="doctools_section"><h2><a name="section2">ELEMENT COMMANDS</a></h2> <dl class="doctools_definitions"> <dt><a name="1"><b class="cmd">tsv::names</b> <span class="opt">?pattern?</span></a></dt> <dd><p>Returns names of shared variables matching optional <span class="opt">?pattern?</span> or all known variables if pattern is ommited.</p></dd> <dt><a name="2"><b class="cmd">tsv::object</b> <i class="arg">varname</i> <i class="arg">element</i></a></dt> <dd><p>Creates object accessor command for the <i class="arg">element</i> in the shared variable <i class="arg">varname</i>. Using this command, one can apply most of the other shared variable commands as method functions of the element object command. The object command is automatically deleted when the element which this command is pointing to is unset.</p> <pre class="doctools_example"> % tsv::set foo bar "A shared string" % set string [tsv::object foo bar] % $string append " appended" => A shared string appended </pre> </dd> <dt><a name="3"><b class="cmd">tsv::set</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?value?</span></a></dt> <dd><p>Sets the value of the <i class="arg">element</i> in the shared variable <i class="arg">varname</i> to <i class="arg">value</i> and returns the value to caller. The <i class="arg">value</i> may be ommited, in which case the command will return the current value of the element. If the element cannot be found, error is triggered.</p></dd> <dt><a name="4"><b class="cmd">tsv::get</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?namedvar?</span></a></dt> <dd><p>Retrieves the value of the <i class="arg">element</i> from the shared variable <i class="arg">varname</i>. If the optional argument <i class="arg">namedvar</i> is given, the value is stored in the named variable. Return value of the command depends of the existence of the optional argument <i class="arg">namedvar</i>. If the argument is ommited and the requested element cannot be found in the shared array, the command triggers error. If, however, the optional argument is given on the command line, the command returns true (1) if the element is found or false (0) if the element is not found.</p></dd> <dt><a name="5"><b class="cmd">tsv::unset</b> <i class="arg">varname</i> <span class="opt">?element?</span></a></dt> <dd><p>Unsets the <i class="arg">element</i> from the shared variable <i class="arg">varname</i>. If the optional element is not given, it deletes the variable.</p></dd> <dt><a name="6"><b class="cmd">tsv::exists</b> <i class="arg">varname</i> <i class="arg">element</i></a></dt> <dd><p>Checks wether the <i class="arg">element</i> exists in the shared variable <i class="arg">varname</i> and returns true (1) if it does or false (0) if it doesn't.</p></dd> <dt><a name="7"><b class="cmd">tsv::pop</b> <i class="arg">varname</i> <i class="arg">element</i></a></dt> <dd><p>Returns value of the <i class="arg">element</i> in the shared variable <i class="arg">varname</i> and unsets the element, all in one atomic operation.</p></dd> <dt><a name="8"><b class="cmd">tsv::move</b> <i class="arg">varname</i> <i class="arg">oldname</i> <i class="arg">newname</i></a></dt> <dd><p>Renames the element <i class="arg">oldname</i> to the <i class="arg">newname</i> in the shared variable <i class="arg">varname</i>. This effectively performs an get/unset/set sequence of operations but all in one atomic step.</p></dd> <dt><a name="9"><b class="cmd">tsv::incr</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?count?</span></a></dt> <dd><p>Similar to standard Tcl <b class="cmd">incr</b> command but increments the value of the <i class="arg">element</i> in shared variaboe <i class="arg">varname</i> instead of the Tcl variable.</p></dd> <dt><a name="10"><b class="cmd">tsv::append</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">value</i> <span class="opt">?value ...?</span></a></dt> <dd><p>Similar to standard Tcl <b class="cmd">append</b> command but appends one or more values to the <i class="arg">element</i> in shared variable <i class="arg">varname</i> instead of the Tcl variable.</p></dd> <dt><a name="11"><b class="cmd">tsv::lock</b> <i class="arg">varname</i> <i class="arg">arg</i> <span class="opt">?arg ...?</span></a></dt> <dd><p>This command concatenates passed arguments and evaluates the resulting script under the internal mutex protection. During the script evaluation, the entire shared variable is locked. For shared variable commands within the script, internal locking is disabled so no deadlock can occur. It is also allowed to unset the shared variable from within the script. The shared variable is automatically created if it did not exists at the time of the first lock operation.</p> <pre class="doctools_example"> % tsv::lock foo { tsv::lappend foo bar 1 tsv::lappend foo bar 2 puts stderr [tsv::set foo bar] tsv::unset foo } </pre> </dd> <dt><a name="12"><b class="cmd">tsv::handlers</b></a></dt> <dd><p>Returns the names of all persistent storage handlers enabled at compile time. See <span class="sectref"><a href="#section4">ARRAY COMMANDS</a></span> for details.</p></dd> </dl> </div> <div id="section3" class="doctools_section"><h2><a name="section3">LIST COMMANDS</a></h2> <p>Those command are similar to the equivalently named Tcl command. The difference is that they operate on elements of shared arrays.</p> <dl class="doctools_definitions"> <dt><a name="13"><b class="cmd">tsv::lappend</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">value</i> <span class="opt">?value ...?</span></a></dt> <dd><p>Similar to standard Tcl <b class="cmd">lappend</b> command but appends one or more values to the <i class="arg">element</i> in shared variable <i class="arg">varname</i> instead of the Tcl variable.</p></dd> <dt><a name="14"><b class="cmd">tsv::linsert</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">index</i> <i class="arg">value</i> <span class="opt">?value ...?</span></a></dt> <dd><p>Similar to standard Tcl <b class="cmd">linsert</b> command but inserts one or more values at the <i class="arg">index</i> list position in the <i class="arg">element</i> in the shared variable <i class="arg">varname</i> instead of the Tcl variable.</p></dd> <dt><a name="15"><b class="cmd">tsv::lreplace</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">first</i> <i class="arg">last</i> <span class="opt">?value ...?</span></a></dt> <dd><p>Similar to standard Tcl <b class="cmd">lreplace</b> command but replaces one or more values between the <i class="arg">first</i> and <i class="arg">last</i> position in the <i class="arg">element</i> of the shared variable <i class="arg">varname</i> instead of the Tcl variable.</p></dd> <dt><a name="16"><b class="cmd">tsv::llength</b> <i class="arg">varname</i> <i class="arg">element</i></a></dt> <dd><p>Similar to standard Tcl <b class="cmd">llength</b> command but returns length of the <i class="arg">element</i> in the shared variable <i class="arg">varname</i> instead of the Tcl variable.</p></dd> <dt><a name="17"><b class="cmd">tsv::lindex</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?index?</span></a></dt> <dd><p>Similar to standard Tcl <b class="cmd">lindex</b> command but returns the value at the <i class="arg">index</i> list position of the <i class="arg">element</i> from the shared variable <i class="arg">varname</i> instead of the Tcl variable.</p></dd> <dt><a name="18"><b class="cmd">tsv::lrange</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">from</i> <i class="arg">to</i></a></dt> <dd><p>Similar to standard Tcl <b class="cmd">lrange</b> command but returns values between <i class="arg">from</i> and <i class="arg">to</i> list positions from the <i class="arg">element</i> in the shared variable <i class="arg">varname</i> instead of the Tcl variable.</p></dd> <dt><a name="19"><b class="cmd">tsv::lsearch</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?options?</span> <i class="arg">pattern</i></a></dt> <dd><p>Similar to standard Tcl <b class="cmd">lsearch</b> command but searches the <i class="arg">element</i> in the shared variable <i class="arg">varname</i> instead of the Tcl variable.</p></dd> <dt><a name="20"><b class="cmd">tsv::lset</b> <i class="arg">varname</i> <i class="arg">element</i> <i class="arg">index</i> <span class="opt">?index ...?</span> <i class="arg">value</i></a></dt> <dd><p>Similar to standard Tcl <b class="cmd">lset</b> command but sets the <i class="arg">element</i> in the shared variable <i class="arg">varname</i> instead of the Tcl variable.</p></dd> <dt><a name="21"><b class="cmd">tsv::lpop</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?index?</span></a></dt> <dd><p>Similar to the standard Tcl <b class="cmd">lindex</b> command but in addition to returning, it also splices the value out of the <i class="arg">element</i> from the shared variable <i class="arg">varname</i> in one atomic operation. In contrast to the Tcl <b class="cmd">lindex</b> command, this command returns no value to the caller.</p></dd> <dt><a name="22"><b class="cmd">tsv::lpush</b> <i class="arg">varname</i> <i class="arg">element</i> <span class="opt">?index?</span></a></dt> <dd><p>This command performes the opposite of the <b class="cmd">tsv::lpop</b> command. As its counterpart, it returns no value to the caller.</p></dd> </dl> </div> <div id="section4" class="doctools_section"><h2><a name="section4">ARRAY COMMANDS</a></h2> <p>This command supports most of the options of the standard Tcl <b class="cmd">array</b> command. In addition to those, it allows binding a shared variable to some persisten storage databases. Currently the persistent options supported are the famous GNU Gdbm and LMDB. These options have to be selected during the package compilation time. The implementation provides hooks for defining other persistency layers, if needed.</p> <dl class="doctools_definitions"> <dt><a name="23"><b class="cmd">tsv::array set</b> <i class="arg">varname</i> <i class="arg">list</i></a></dt> <dd><p>Does the same as standard Tcl <b class="cmd">array set</b>.</p></dd> <dt><a name="24"><b class="cmd">tsv::array get</b> <i class="arg">varname</i> <span class="opt">?pattern?</span></a></dt> <dd><p>Does the same as standard Tcl <b class="cmd">array get</b>.</p></dd> <dt><a name="25"><b class="cmd">tsv::array names</b> <i class="arg">varname</i> <span class="opt">?pattern?</span></a></dt> <dd><p>Does the same as standard Tcl <b class="cmd">array names</b>.</p></dd> <dt><a name="26"><b class="cmd">tsv::array size</b> <i class="arg">varname</i></a></dt> <dd><p>Does the same as standard Tcl <b class="cmd">array size</b>.</p></dd> <dt><a name="27"><b class="cmd">tsv::array reset</b> <i class="arg">varname</i> <i class="arg">list</i></a></dt> <dd><p>Does the same as standard Tcl <b class="cmd">array set</b> but it clears the <i class="arg">varname</i> and sets new values from the list atomically.</p></dd> <dt><a name="28"><b class="cmd">tsv::array bind</b> <i class="arg">varname</i> <i class="arg">handle</i></a></dt> <dd><p>Binds the <i class="arg">varname</i> to the persistent storage <i class="arg">handle</i>. The format of the <i class="arg">handle</i> is <handler>:<address>, where <handler> is "gdbm" for GNU Gdbm and "lmdb" for LMDB and <address> is the path to the database file.</p></dd> <dt><a name="29"><b class="cmd">tsv::array unbind</b> <i class="arg">varname</i></a></dt> <dd><p>Unbinds the shared <i class="arg">array</i> from its bound persistent storage.</p></dd> <dt><a name="30"><b class="cmd">tsv::array isbound</b> <i class="arg">varname</i></a></dt> <dd><p>Returns true (1) if the shared <i class="arg">varname</i> is bound to some persistent storage or zero (0) if not.</p></dd> </dl> </div> <div id="section5" class="doctools_section"><h2><a name="section5">KEYED LIST COMMANDS</a></h2> <p>Keyed list commands are borrowed from the TclX package. Keyed lists provide a structured data type built upon standard Tcl lists. This is a functionality similar to structs in the C programming language.</p> <p>A keyed list is a list in which each element contains a key and value pair. These element pairs are stored as lists themselves, where the key is the first element of the list, and the value is the second. The key-value pairs are referred to as fields. This is an example of a keyed list:</p> <pre class="doctools_example"> {{NAME {Frank Zappa}} {JOB {musician and composer}}} </pre> <p>Fields may contain subfields; `.' is the separator character. Subfields are actually fields where the value is another keyed list. Thus the following list has the top level fields ID and NAME, and subfields NAME.FIRST and NAME.LAST:</p> <pre class="doctools_example"> {ID 106} {NAME {{FIRST Frank} {LAST Zappa}}} </pre> <p>There is no limit to the recursive depth of subfields, allowing one to build complex data structures. Keyed lists are constructed and accessed via a number of commands. All keyed list management commands take the name of the variable containing the keyed list as an argument (i.e. passed by reference), rather than passing the list directly.</p> <dl class="doctools_definitions"> <dt><a name="31"><b class="cmd">tsv::keyldel</b> <i class="arg">varname</i> <i class="arg">keylist</i> <i class="arg">key</i></a></dt> <dd><p>Delete the field specified by <i class="arg">key</i> from the keyed list <i class="arg">keylist</i> in the shared variable <i class="arg">varname</i>. This removes both the key and the value from the keyed list.</p></dd> <dt><a name="32"><b class="cmd">tsv::keylget</b> <i class="arg">varname</i> <i class="arg">keylist</i> <i class="arg">key</i> <span class="opt">?retvar?</span></a></dt> <dd><p>Return the value associated with <i class="arg">key</i> from the keyed list <i class="arg">keylist</i> in the shared variable <i class="arg">varname</i>. If the optional <i class="arg">retvar</i> is not specified, then the value will be returned as the result of the command. In this case, if key is not found in the list, an error will result.</p> <p>If <i class="arg">retvar</i> is specified and <i class="arg">key</i> is in the list, then the value is returned in the variable <i class="arg">retvar</i> and the command returns 1 if the key was present within the list. If <i class="arg">key</i> isn't in the list, the command will return 0, and <i class="arg">retvar</i> will be left unchanged. If {} is specified for <i class="arg">retvar</i>, the value is not returned, allowing the Tcl programmer to determine if a <i class="arg">key</i> is present in a keyed list without setting a variable as a side-effect.</p></dd> <dt><a name="33"><b class="cmd">tsv::keylkeys</b> <i class="arg">varname</i> <i class="arg">keylist</i> <span class="opt">?key?</span></a></dt> <dd><p>Return the a list of the keys in the keyed list <i class="arg">keylist</i> in the shared variable <i class="arg">varname</i>. If <i class="arg">key</i> is specified, then it is the name of a key field who's subfield keys are to be retrieved.</p></dd> <dt><a name="34"><b class="cmd">tsv::keylset</b> <i class="arg">varname</i> <i class="arg">keylist</i> <i class="arg">key</i> <i class="arg">value</i> <span class="opt">?key value..?</span></a></dt> <dd><p>Set the value associated with <i class="arg">key</i>, in the keyed list <i class="arg">keylist</i> to <i class="arg">value</i>. If the <i class="arg">keylist</i> does not exists, it is created. If <i class="arg">key</i> is not currently in the list, it will be added. If it already exists, <i class="arg">value</i> replaces the existing value. Multiple keywords and values may be specified, if desired.</p></dd> </dl> </div> <div id="section6" class="doctools_section"><h2><a name="section6">DISCUSSION</a></h2> <p>The current implementation of thread shared variables allows for easy and convenient access to data shared between different threads. Internally, the data is stored in Tcl objects and all package commands operate on internal data representation, thus minimizing shimmering and improving performance. Special care has been taken to assure that all object data is properly locked and deep-copied when moving objects between threads.</p> <p>Due to the internal design of the Tcl core, there is no provision of full integration of shared variables within the Tcl syntax, unfortunately. All access to shared data must be performed with the supplied package commands. Also, variable traces are not supported. But even so, benefits of easy, simple and safe shared data manipulation outweights imposed limitations.</p> </div> <div id="section7" class="doctools_section"><h2><a name="section7">CREDITS</a></h2> <p>Thread shared variables are inspired by the nsv interface found in AOLserver, a highly scalable Web server from America Online.</p> </div> <div id="see-also" class="doctools_section"><h2><a name="see-also">See Also</a></h2> <p>thread, tpool, ttrace</p> </div> <div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2> <p>locking, synchronization, thread shared data, threads</p> </div> </div></body></html> |
Changes to doc/html/ttrace.html.
|
| | < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | | | < | | | | | | < < | < | | | | | > > | > > > > | | < | | | | | | | | | | | | | | | | | | < | > > | | < | | < | | | < < | < < < < < | < | | | | < | | | < | < < < | | < | | < < | < < | | < < | < < | | < < | < < | | | < < < < | | | < < | < < | | | < | | < | | | | < | | | | < < < < < | | | | | < < < < < | | | | | < < < < < | | | | | | < < < < < | | | | < < < < | | | < < | < < | | | < < < < | | < < < < | | < < < < | < < | < < | | < < < < | | < | | < | | | | | < | < | | | < < < < < | > | < | > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 | <html><head> <title>ttrace - Tcl Threading</title> <style type="text/css"><!-- HTML { background: #FFFFFF; color: black; } BODY { background: #FFFFFF; color: black; } DIV.doctools { margin-left: 10%; margin-right: 10%; } DIV.doctools H1,DIV.doctools H2 { margin-left: -5%; } H1, H2, H3, H4 { margin-top: 1em; font-family: sans-serif; font-size: large; color: #005A9C; background: transparent; text-align: left; } H1.doctools_title { text-align: center; } UL,OL { margin-right: 0em; margin-top: 3pt; margin-bottom: 3pt; } UL LI { list-style: disc; } OL LI { list-style: decimal; } DT { padding-top: 1ex; } UL.doctools_toc,UL.doctools_toc UL, UL.doctools_toc UL UL { font: normal 12pt/14pt sans-serif; list-style: none; } LI.doctools_section, LI.doctools_subsection { list-style: none; margin-left: 0em; text-indent: 0em; padding: 0em; } PRE { display: block; font-family: monospace; white-space: pre; margin: 0%; padding-top: 0.5ex; padding-bottom: 0.5ex; padding-left: 1ex; padding-right: 1ex; width: 100%; } PRE.doctools_example { color: black; background: #f5dcb3; border: 1px solid black; } UL.doctools_requirements LI, UL.doctools_syntax LI { list-style: none; margin-left: 0em; text-indent: 0em; padding: 0em; } DIV.doctools_synopsis { color: black; background: #80ffff; border: 1px solid black; font-family: serif; margin-top: 1em; margin-bottom: 1em; } UL.doctools_syntax { margin-top: 1em; border-top: 1px solid black; } UL.doctools_requirements { margin-bottom: 1em; border-bottom: 1px solid black; } --></style> </head> <! -- Generated from file '' by tcllib/doctools with format 'html' --> <! -- ttrace.n --> <body><div class="doctools"> <h1 class="doctools_title">ttrace(n) 2.8 "Tcl Threading"</h1> <div id="name" class="doctools_section"><h2><a name="name">Name</a></h2> <p>ttrace - Trace-based interpreter initialization</p> </div> <div id="toc" class="doctools_section"><h2><a name="toc">Table Of Contents</a></h2> <ul class="doctools_toc"> <li class="doctools_section"><a href="#toc">Table Of Contents</a></li> <li class="doctools_section"><a href="#synopsis">Synopsis</a></li> <li class="doctools_section"><a href="#section1">Description</a></li> <li class="doctools_section"><a href="#section2">USER COMMANDS</a></li> <li class="doctools_section"><a href="#section3">CALLBACK COMMANDS</a></li> <li class="doctools_section"><a href="#section4">DISCUSSION</a></li> <li class="doctools_section"><a href="#see-also">See Also</a></li> <li class="doctools_section"><a href="#keywords">Keywords</a></li> </ul> </div> <div id="synopsis" class="doctools_section"><h2><a name="synopsis">Synopsis</a></h2> <div class="doctools_synopsis"> <ul class="doctools_requirements"> <li>package require <b class="pkgname">Tcl 8.4</b></li> <li>package require <b class="pkgname">Thread <span class="opt">?2.8?</span></b></li> </ul> <ul class="doctools_syntax"> <li><a href="#1"><b class="cmd">ttrace::eval</b> <i class="arg">arg</i> <span class="opt">?arg ...?</span></a></li> <li><a href="#2"><b class="cmd">ttrace::enable</b></a></li> <li><a href="#3"><b class="cmd">ttrace::disable</b></a></li> <li><a href="#4"><b class="cmd">ttrace::cleanup</b></a></li> <li><a href="#5"><b class="cmd">ttrace::update</b> <span class="opt">?epoch?</span></a></li> <li><a href="#6"><b class="cmd">ttrace::getscript</b></a></li> <li><a href="#7"><b class="cmd">ttrace::atenable</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></li> <li><a href="#8"><b class="cmd">ttrace::atdisable</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></li> <li><a href="#9"><b class="cmd">ttrace::addtrace</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></li> <li><a href="#10"><b class="cmd">ttrace::addscript</b> <i class="arg">name</i> <i class="arg">body</i></a></li> <li><a href="#11"><b class="cmd">ttrace::addresolver</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></li> <li><a href="#12"><b class="cmd">ttrace::addcleanup</b> <i class="arg">body</i></a></li> <li><a href="#13"><b class="cmd">ttrace::addentry</b> <i class="arg">cmd</i> <i class="arg">var</i> <i class="arg">val</i></a></li> <li><a href="#14"><b class="cmd">ttrace::getentry</b> <i class="arg">cmd</i> <i class="arg">var</i></a></li> <li><a href="#15"><b class="cmd">ttrace::getentries</b> <i class="arg">cmd</i> <span class="opt">?pattern?</span></a></li> <li><a href="#16"><b class="cmd">ttrace::delentry</b> <i class="arg">cmd</i></a></li> <li><a href="#17"><b class="cmd">ttrace::preload</b> <i class="arg">cmd</i></a></li> </ul> </div> </div> <div id="section1" class="doctools_section"><h2><a name="section1">Description</a></h2> <p>This package creates a framework for on-demand replication of the interpreter state accross threads in an multithreading application. It relies on the mechanics of Tcl command tracing and the Tcl <b class="cmd">unknown</b> command and mechanism.</p> <p>The package requires Tcl threading extension but can be alternatively used stand-alone within the AOLserver, a scalable webserver from America Online.</p> <p>In a nutshell, a short sample illustrating the usage of the ttrace with the Tcl threading extension:</p> <pre class="doctools_example"> % package require Ttrace 2.8.0 % set t1 [thread::create {package require Ttrace; thread::wait}] tid0x1802800 % ttrace::eval {proc test args {return test-[thread::id]}} % thread::send $t1 test test-tid0x1802800 % set t2 [thread::create {package require Ttrace; thread::wait}] tid0x1804000 % thread::send $t2 test test-tid0x1804000 </pre> <p>As seen from above, the <b class="cmd">ttrace::eval</b> and <b class="cmd">ttrace::update</b> commands are used to create a thread-wide definition of a simple Tcl procedure and replicate that definition to all, already existing or later created, threads.</p> </div> <div id="section2" class="doctools_section"><h2><a name="section2">USER COMMANDS</a></h2> <p>This section describes user-level commands. Those commands can be used by script writers to control the execution of the tracing framework.</p> <dl class="doctools_definitions"> <dt><a name="1"><b class="cmd">ttrace::eval</b> <i class="arg">arg</i> <span class="opt">?arg ...?</span></a></dt> <dd><p>This command concatenates given arguments and evaluates the resulting Tcl command with trace framework enabled. If the command execution was ok, it takes necessary steps to automatically propagate the trace epoch change to all threads in the application. For AOLserver, only newly created threads actually receive the epoch change. For the Tcl threading extension, all threads created by the extension are automatically updated. If the command execution resulted in Tcl error, no state propagation takes place.</p> <p>This is the most important user-level command of the package as it wraps most of the commands described below. This greatly simplifies things, because user need to learn just this (one) command in order to effectively use the package. Other commands, as desribed below, are included mostly for the sake of completeness.</p></dd> <dt><a name="2"><b class="cmd">ttrace::enable</b></a></dt> <dd><p>Activates all registered callbacks in the framework and starts a new trace epoch. The trace epoch encapsulates all changes done to the interpreter during the time traces are activated.</p></dd> <dt><a name="3"><b class="cmd">ttrace::disable</b></a></dt> <dd><p>Deactivates all registered callbacks in the framework and closes the current trace epoch.</p></dd> <dt><a name="4"><b class="cmd">ttrace::cleanup</b></a></dt> <dd><p>Used to clean-up all on-demand loaded resources in the interpreter. It effectively brings Tcl interpreter to its pristine state.</p></dd> <dt><a name="5"><b class="cmd">ttrace::update</b> <span class="opt">?epoch?</span></a></dt> <dd><p>Used to refresh the state of the interpreter to match the optional trace <span class="opt">?epoch?</span>. If the optional <span class="opt">?epoch?</span> is not given, it takes the most recent trace epoch.</p></dd> <dt><a name="6"><b class="cmd">ttrace::getscript</b></a></dt> <dd><p>Returns a synthetized Tcl script which may be sourced in any interpreter. This script sets the stage for the Tcl <b class="cmd">unknown</b> command so it can load traced resources from the in-memory database. Normally, this command is automatically invoked by other higher-level commands like <b class="cmd">ttrace::eval</b> and <b class="cmd">ttrace::update</b>.</p></dd> </dl> </div> <div id="section3" class="doctools_section"><h2><a name="section3">CALLBACK COMMANDS</a></h2> <p>A word upfront: the package already includes callbacks for tracing following Tcl commands: <b class="cmd">proc</b>, <b class="cmd">namespace</b>, <b class="cmd">variable</b>, <b class="cmd">load</b>, and <b class="cmd">rename</b>. Additionaly, a set of callbacks for tracing resources (object, clasess) for the XOTcl v1.3.8+, an OO-extension to Tcl, is also provided. This gives a solid base for solving most of the real-life needs and serves as an example for people wanting to customize the package to cover their specific needs.</p> <p>Below, you can find commands for registering callbacks in the framework and for writing callback scripts. These callbacks are invoked by the framework in order to gather interpreter state changes, build in-memory database, perform custom-cleanups and various other tasks.</p> <dl class="doctools_definitions"> <dt><a name="7"><b class="cmd">ttrace::atenable</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></dt> <dd><p>Registers Tcl callback to be activated at <b class="cmd">ttrace::enable</b>. Registered callbacks are activated on FIFO basis. The callback definition includes the name of the callback, <i class="arg">cmd</i>, a list of callback arguments, <i class="arg">arglist</i> and the <i class="arg">body</i> of the callback. Effectively, this actually resembles the call interface of the standard Tcl <b class="cmd">proc</b> command.</p></dd> <dt><a name="8"><b class="cmd">ttrace::atdisable</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></dt> <dd><p>Registers Tcl callback to be activated at <b class="cmd">ttrace::disable</b>. Registered callbacks are activated on FIFO basis. The callback definition includes the name of the callback, <i class="arg">cmd</i>, a list of callback arguments, <i class="arg">arglist</i> and the <i class="arg">body</i> of the callback. Effectively, this actually resembles the call interface of the standard Tcl <b class="cmd">proc</b> command.</p></dd> <dt><a name="9"><b class="cmd">ttrace::addtrace</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></dt> <dd><p>Registers Tcl callback to be activated for tracing the Tcl <b class="cmd">cmd</b> command. The callback definition includes the name of the Tcl command to trace, <i class="arg">cmd</i>, a list of callback arguments, <i class="arg">arglist</i> and the <i class="arg">body</i> of the callback. Effectively, this actually resembles the call interface of the standard Tcl <b class="cmd">proc</b> command.</p></dd> <dt><a name="10"><b class="cmd">ttrace::addscript</b> <i class="arg">name</i> <i class="arg">body</i></a></dt> <dd><p>Registers Tcl callback to be activated for building a Tcl script to be passed to other interpreters. This script is used to set the stage for the Tcl <b class="cmd">unknown</b> command. Registered callbacks are activated on FIFO basis. The callback definition includes the name of the callback, <i class="arg">name</i> and the <i class="arg">body</i> of the callback.</p></dd> <dt><a name="11"><b class="cmd">ttrace::addresolver</b> <i class="arg">cmd</i> <i class="arg">arglist</i> <i class="arg">body</i></a></dt> <dd><p>Registers Tcl callback to be activated by the overloaded Tcl <b class="cmd">unknown</b> command. Registered callbacks are activated on FIFO basis. This callback is used to resolve the resource and load the resource in the current interpreter.</p></dd> <dt><a name="12"><b class="cmd">ttrace::addcleanup</b> <i class="arg">body</i></a></dt> <dd><p>Registers Tcl callback to be activated by the <b class="cmd">trace::cleanup</b>. Registered callbacks are activated on FIFO basis.</p></dd> <dt><a name="13"><b class="cmd">ttrace::addentry</b> <i class="arg">cmd</i> <i class="arg">var</i> <i class="arg">val</i></a></dt> <dd><p>Adds one entry to the named in-memory database.</p></dd> <dt><a name="14"><b class="cmd">ttrace::getentry</b> <i class="arg">cmd</i> <i class="arg">var</i></a></dt> <dd><p>Returns the value of the entry from the named in-memory database.</p></dd> <dt><a name="15"><b class="cmd">ttrace::getentries</b> <i class="arg">cmd</i> <span class="opt">?pattern?</span></a></dt> <dd><p>Returns names of all entries from the named in-memory database.</p></dd> <dt><a name="16"><b class="cmd">ttrace::delentry</b> <i class="arg">cmd</i></a></dt> <dd><p>Deletes an entry from the named in-memory database.</p></dd> <dt><a name="17"><b class="cmd">ttrace::preload</b> <i class="arg">cmd</i></a></dt> <dd><p>Registers the Tcl command to be loaded in the interpreter. Commands registered this way will always be the part of the interpreter and not be on-demand loaded by the Tcl <b class="cmd">unknown</b> command.</p></dd> </dl> </div> <div id="section4" class="doctools_section"><h2><a name="section4">DISCUSSION</a></h2> <p>Common introspective state-replication approaches use a custom Tcl script to introspect the running interpreter and synthesize another Tcl script to replicate this state in some other interpreter. This package, on the contrary, uses Tcl command traces. Command traces are registered on selected Tcl commands, like <b class="cmd">proc</b>, <b class="cmd">namespace</b>, <b class="cmd">load</b> and other standard (and/or user-defined) Tcl commands. When activated, those traces build an in-memory database of created resources. This database is used as a resource repository for the (overloaded) Tcl <b class="cmd">unknown</b> command which creates the requested resource in the interpreter on demand. This way, users can update just one interpreter (master) in one thread and replicate that interpreter state (or part of it) to other threads/interpreters in the process.</p> <p>Immediate benefit of such approach is the much smaller memory footprint of the application and much faster thread creation. By not actually loading all necessary procedures (and other resources) in every thread at the thread initialization time, but by deffering this to the time the resource is actually referenced, significant improvements in both memory consumption and thread initialization time can be achieved. Some tests have shown that memory footprint of an multithreading Tcl application went down more than three times and thread startup time was reduced for about 50 times. Note that your mileage may vary. Other benefits include much finer control about what (and when) gets replicated from the master to other Tcl thread/interpreters.</p> </div> <div id="see-also" class="doctools_section"><h2><a name="see-also">See Also</a></h2> <p>thread, tpool, tsv</p> </div> <div id="keywords" class="doctools_section"><h2><a name="keywords">Keywords</a></h2> <p>command tracing, introspection</p> </div> </div></body></html> |
Changes to doc/man/thread.n.
1 2 3 | '\" '\" Generated from file '' by tcllib/doctools with format 'nroff' '\" | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > | < < < < < < < | | | | | | | | > > > > > > > > > | < < < < < < < < | | | | | | | | | > > > > > > > | | | | | | | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | '\" '\" Generated from file '' by tcllib/doctools with format 'nroff' '\" .TH "thread" n 2\&.8 "Tcl Threading" .\" The -*- nroff -*- definitions below are for supplemental macros used .\" in Tcl/Tk manual entries. .\" .\" .AP type name in/out ?indent? .\" Start paragraph describing an argument to a library procedure. .\" type is type of argument (int, etc.), in/out is either "in", "out", .\" or "in/out" to describe whether procedure reads or modifies arg, .\" and indent is equivalent to second arg of .IP (shouldn't ever be .\" needed; use .AS below instead) .\" .\" .AS ?type? ?name? .\" Give maximum sizes of arguments for setting tab stops. Type and .\" name are examples of largest possible arguments that will be passed .\" to .AP later. If args are omitted, default tab stops are used. .\" .\" .BS .\" Start box enclosure. From here until next .BE, everything will be .\" enclosed in one large box. .\" .\" .BE .\" End of box enclosure. .\" .\" .CS .\" Begin code excerpt. .\" .\" .CE .\" End code excerpt. .\" .\" .VS ?version? ?br? .\" Begin vertical sidebar, for use in marking newly-changed parts .\" of man pages. The first argument is ignored and used for recording .\" the version when the .VS was added, so that the sidebars can be .\" found and removed when they reach a certain age. If another argument .\" is present, then a line break is forced before starting the sidebar. .\" .\" .VE .\" End of vertical sidebar. .\" .\" .DS .\" Begin an indented unfilled display. .\" .\" .DE .\" End of indented unfilled display. .\" .\" .SO ?manpage? .\" Start of list of standard options for a Tk widget. The manpage .\" argument defines where to look up the standard options; if .\" omitted, defaults to "options". The options follow on successive .\" lines, in three columns separated by tabs. .\" .\" .SE .\" End of list of standard options for a Tk widget. .\" .\" .OP cmdName dbName dbClass .\" Start of description of a specific option. cmdName gives the .\" option's name as specified in the class command, dbName gives .\" the option's name in the option database, and dbClass gives .\" the option's class in the option database. .\" .\" .UL arg1 arg2 .\" Print arg1 underlined, then print arg2 normally. .\" .\" .QW arg1 ?arg2? .\" Print arg1 in quotes, then arg2 normally (for trailing punctuation). .\" .\" .PQ arg1 ?arg2? .\" Print an open parenthesis, arg1 in quotes, then arg2 normally .\" (for trailing punctuation) and then a closing parenthesis. .\" .\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages. .if t .wh -1.3i ^B .nr ^l \n(.l .ad b .\" # Start an argument description .de AP .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} .ta \\n()Au \\n()Bu .ie !"\\$3"" \{\ \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br .ie !"\\$2"" \{\ \&\\$1 \\fI\\$2\\fP .\} .el \{\ \&\\fI\\$1\\fP .\} .\} .. .\" # define tabbing values for .AP .de AS .nr )A 10n .if !"\\$1"" .nr )A \\w'\\$1'u+3n .nr )B \\n()Au+15n .\" .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n .nr )C \\n()Bu+\\w'(in/out)'u+2n .. .AS Tcl_Interp Tcl_CreateInterp in/out .\" # BS - start boxed text .\" # ^y = starting y location .\" # ^b = 1 .de BS .br .mk ^y .nr ^b 1u .if n .nf .if n .ti 0 .if n \l'\\n(.lu\(ul' .if n .fi .. .\" # BE - end boxed text (draw box now) .de BE .nf .ti 0 .mk ^t .ie n \l'\\n(^lu\(ul' .el \{\ .\" Draw four-sided box normally, but don't draw top of .\" box if the box started on an earlier page. .ie !\\n(^b-1 \{\ \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .el \}\ \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .\} .fi .br .nr ^b 0 .. .\" # VS - start vertical sidebar .\" # ^Y = starting y location .\" # ^v = 1 (for troff; for nroff this doesn't matter) .de VS .if !"\\$2"" .br .mk ^Y .ie n 'mc \s12\(br\s0 .el .nr ^v 1u .. .\" # VE - end of vertical sidebar .de VE .ie n 'mc .el \{\ .ev 2 .nf .ti 0 .mk ^t \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' .sp -1 .fi .ev .\} .nr ^v 0 .. .\" # Special macro to handle page bottom: finish off current .\" # box/sidebar if in box/sidebar mode, then invoked standard .\" # page bottom macro. .de ^B .ev 2 'ti 0 'nf .mk ^t .if \\n(^b \{\ .\" Draw three-sided box if this is the box's first page, |
︙ | ︙ | |||
180 181 182 183 184 185 186 | .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. | | | | > > | | | | < | < > | > > > > > > > > > > > > > > > > > > > | > | | | | > > | | | | | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. .\" # DS - begin display .de DS .RS .nf .sp .. .\" # DE - end display .de DE .fi .RE .sp .. .\" # SO - start of list of standard options .de SO 'ie '\\$1'' .ds So \\fBoptions\\fR 'el .ds So \\fB\\$1\\fR .SH "STANDARD OPTIONS" .LP .nf .ta 5.5c 11c .ft B .. .\" # SE - end of list of standard options .de SE .fi .ft R .LP See the \\*(So manual entry for details on the standard options. .. .\" # OP - start of full description for a single option .de OP .LP .nf .ta 4c Command-Line Name: \\fB\\$1\\fR Database Name: \\fB\\$2\\fR Database Class: \\fB\\$3\\fR .fi .IP .. .\" # CS - begin code excerpt .de CS .RS .nf .ta .25i .5i .75i 1i .. .\" # CE - end code excerpt .de CE .fi .RE .. .\" # UL - underline word .de UL \\$1\l'|0\(ul'\\$2 .. .\" # QW - apply quotation marks to word .de QW .ie '\\*(lq'"' ``\\$1''\\$2 .\"" fix emacs highlighting .el \\*(lq\\$1\\*(rq\\$2 .. .\" # PQ - apply parens and quotation marks to word .de PQ .ie '\\*(lq'"' (``\\$1''\\$2)\\$3 .\"" fix emacs highlighting .el (\\*(lq\\$1\\*(rq\\$2)\\$3 .. .\" # QR - quoted range .de QR .ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3 .\"" fix emacs highlighting .el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3 .. .\" # MT - "empty" string .de MT .QW "" .. .BS .SH NAME thread \- Extension for script access to Tcl threading .SH SYNOPSIS package require \fBTcl 8\&.4\fR .sp package require \fBThread ?2\&.8?\fR .sp \fBthread::create\fR ?-joinable? ?-preserved? ?script? .sp \fBthread::preserve\fR ?id? .sp \fBthread::release\fR ?-wait? ?id? .sp \fBthread::id\fR .sp \fBthread::errorproc\fR ?procname? .sp \fBthread::cancel\fR ?-unwind? \fIid\fR ?result? .sp \fBthread::unwind\fR .sp \fBthread::exit\fR ?status? .sp \fBthread::names\fR .sp \fBthread::exists\fR \fIid\fR .sp \fBthread::send\fR ?-async? ?-head? \fIid\fR \fIscript\fR ?varname? .sp \fBthread::broadcast\fR \fIscript\fR .sp \fBthread::wait\fR .sp \fBthread::eval\fR ?-lock mutex? \fIarg\fR ?arg \&.\&.\&.? .sp \fBthread::join\fR \fIid\fR .sp \fBthread::configure\fR \fIid\fR ?option? ?value? ?\&.\&.\&.? .sp \fBthread::transfer\fR \fIid\fR \fIchannel\fR .sp \fBthread::detach\fR \fIchannel\fR .sp \fBthread::attach\fR \fIchannel\fR .sp |
︙ | ︙ | |||
313 314 315 316 317 318 319 | \fBthread::cond\fR \fBdestroy\fR \fIcond\fR .sp \fBthread::cond\fR \fBnotify\fR \fIcond\fR .sp \fBthread::cond\fR \fBwait\fR \fIcond\fR \fImutex\fR ?ms? .sp .BE | | | | | | | | | | | | | | | | | | | | | | | | | | | > > | | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > | > > > > > > > > > > > > > > | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | > > | > > | | | | | | | | | | | | | | | > > | > | | | | | | | | | | | | | | | | | | | | | | | > > | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > | > > | > | | | | | | | | | | | 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 | \fBthread::cond\fR \fBdestroy\fR \fIcond\fR .sp \fBthread::cond\fR \fBnotify\fR \fIcond\fR .sp \fBthread::cond\fR \fBwait\fR \fIcond\fR \fImutex\fR ?ms? .sp .BE .SH DESCRIPTION The \fBthread\fR extension creates threads that contain Tcl interpreters, and it lets you send scripts to those threads for evaluation\&. Additionaly, it provides script-level access to basic thread synchronization primitives, like mutexes and condition variables\&. .SH COMMANDS This section describes commands for creating and destroying threads and sending scripts to threads for evaluation\&. .TP \fBthread::create\fR ?-joinable? ?-preserved? ?script? This command creates a thread that contains a Tcl interpreter\&. The Tcl interpreter either evaluates the optional \fBscript\fR, if specified, or it waits in the event loop for scripts that arrive via the \fBthread::send\fR command\&. The result, if any, of the optional \fBscript\fR is never returned to the caller\&. The result of \fBthread::create\fR is the ID of the thread\&. This is the opaque handle which identifies the newly created thread for all other package commands\&. The handle of the thread goes out of scope automatically when thread is marked for exit (see the \fBthread::release\fR command below)\&. .sp If the optional \fBscript\fR argument contains the \fBthread::wait\fR command the thread will enter into the event loop\&. If such command is not found in the \fBscript\fR the thread will run the \fBscript\fR to the end and exit\&. In that case, the handle may be safely ignored since it refers to a thread which does not exists any more at the time when the command returns\&. .sp Using flag \fB-joinable\fR it is possible to create a joinable thread, i\&.e\&. one upon whose exit can be waited upon by using \fBthread::join\fR command\&. Note that failure to join a thread created with \fB-joinable\fR flag results in resource and memory leaks\&. .sp Threads created by the \fBthread::create\fR cannot be destroyed forcefully\&. Consequently, there is no corresponding thread destroy command\&. A thread may only be released using the \fBthread::release\fR and if its internal reference count drops to zero, the thread is marked for exit\&. This kicks the thread out of the event loop servicing and the thread continues to execute commands passed in the \fBscript\fR argument, following the \fBthread::wait\fR command\&. If this was the last command in the script, as usualy the case, the thread will exit\&. .sp It is possible to create a situation in which it may be impossible to terminate the thread, for example by putting some endless loop after the \fBthread::wait\fR or entering the event loop again by doing an vwait-type of command\&. In such cases, the thread may never exit\&. This is considered to be a bad practice and should be avoided if possible\&. This is best illustrated by the example below: .CS # You should never do \&.\&.\&. set tid [thread::create { package require Http thread::wait vwait forever ; # <-- this! }] .CE .IP The thread created in the above example will never be able to exit\&. After it has been released with the last matching \fBthread::release\fR call, the thread will jump out of the \fBthread::wait\fR and continue to execute commands following\&. It will enter \fBvwait\fR command and wait endlessly for events\&. There is no way one can terminate such thread, so you wouldn't want to do this! .sp Each newly created has its internal reference counter set to 0 (zero), i\&.e\&. it is unreserved\&. This counter gets incremented by a call to \fBthread::preserve\fR and decremented by a call to \fBthread::release\fR command\&. These two commands implement simple but effective thread reservation system and offer predictable and controllable thread termination capabilities\&. It is however possible to create initialy preserved threads by using flag \fB-preserved\fR of the \fBthread::create\fR command\&. Threads created with this flag have the initial value of the reference counter of 1 (one), and are thus initially marked reserved\&. .TP \fBthread::preserve\fR ?id? This command increments the thread reference counter\&. Each call to this command increments the reference counter by one (1)\&. Command returns the value of the reference counter after the increment\&. If called with the optional thread \fBid\fR, the command preserves the given thread\&. Otherwise the current thread is preserved\&. .sp With reference counting, one can implement controlled access to a shared Tcl thread\&. By incrementing the reference counter, the caller signalizes that he/she wishes to use the thread for a longer period of time\&. By decrementing the counter, caller signalizes that he/she has finished using the thread\&. .TP \fBthread::release\fR ?-wait? ?id? This command decrements the thread reference counter\&. Each call to this command decrements the reference counter by one (1)\&. If called with the optional thread \fBid\fR, the command releases the given thread\&. Otherwise, the current thread is released\&. Command returns the value of the reference counter after the decrement\&. When the reference counter reaches zero (0), the target thread is marked for termination\&. You should not reference the thread after the \fBthread::release\fR command returns zero or negative integer\&. The handle of the thread goes out of scope and should not be used any more\&. Any following reference to the same thread handle will result in Tcl error\&. .sp Optional flag \fB-wait\fR instructs the caller thread to wait for the target thread to exit, if the effect of the command would result in termination of the target thread, i\&.e\&. if the return result would be zero (0)\&. Without the flag, the caller thread does not wait for the target thread to exit\&. Care must be taken when using the \fB-wait\fR, since this may block the caller thread indefinitely\&. This option has been implemented for some special uses of the extension and is deprecated for regular use\&. Regular users should create joinable threads by using the \fB-joinable\fR option of the \fBthread::create\fR command and the \fBthread::join\fR to wait for thread to exit\&. .TP \fBthread::id\fR This command returns the ID of the current thread\&. .TP \fBthread::errorproc\fR ?procname? This command sets a handler for errors that occur in scripts sent asynchronously, using the \fB-async\fR flag of the \fBthread::send\fR command, to other threads\&. If no handler is specified, the current handler is returned\&. The empty string resets the handler to default (unspecified) value\&. An uncaught error in a thread causes an error message to be sent to the standard error channel\&. This default reporting scheme can be changed by registering a procedure which is called to report the error\&. The \fIprocname\fR is called in the interpreter that invoked the \fBthread::errorproc\fR command\&. The \fIprocname\fR is called like this: .CS myerrorproc thread_id errorInfo .CE .TP \fBthread::cancel\fR ?-unwind? \fIid\fR ?result? This command requires Tcl version 8\&.6 or higher\&. .sp Cancels the script being evaluated in the thread given by the \fIid\fR parameter\&. Without the \fB-unwind\fR switch the evaluation stack for the interpreter is unwound until an enclosing catch command is found or there are no further invocations of the interpreter left on the call stack\&. With the \fB-unwind\fR switch the evaluation stack for the interpreter is unwound without regard to any intervening catch command until there are no further invocations of the interpreter left on the call stack\&. If \fIresult\fR is present, it will be used as the error message string; otherwise, a default error message string will be used\&. .TP \fBthread::unwind\fR Use of this command is deprecated in favour of more advanced thread reservation system implemented with \fBthread::preserve\fR and \fBthread::release\fR commands\&. Support for \fBthread::unwind\fR command will dissapear in some future major release of the extension\&. .sp This command stops a prior \fBthread::wait\fR command\&. Execution of the script passed to newly created thread will continue from the \fBthread::wait\fR command\&. If \fBthread::wait\fR was the last command in the script, the thread will exit\&. The command returns empty result but may trigger Tcl error with the message "target thread died" in some situations\&. .TP \fBthread::exit\fR ?status? Use of this command is deprecated in favour of more advanced thread reservation system implemented with \fBthread::preserve\fR and \fBthread::release\fR commands\&. Support for \fBthread::exit\fR command will dissapear in some future major release of the extension\&. .sp This command forces a thread stuck in the \fBthread::wait\fR command to unconditionaly exit\&. The thread's exit status defaults to 666 and can be specified using the optional \fIstatus\fR argument\&. The execution of \fBthread::exit\fR command is guaranteed to leave the program memory in the unconsistent state, produce memory leaks and otherwise affect other subsytem(s) of the Tcl application in an unpredictable manner\&. The command returns empty result but may trigger Tcl error with the message "target thread died" in some situations\&. .TP \fBthread::names\fR This command returns a list of thread IDs\&. These are only for threads that have been created via \fBthread::create\fR command\&. If your application creates other threads at the C level, they are not reported by this command\&. .TP \fBthread::exists\fR \fIid\fR Returns true (1) if thread given by the \fIid\fR parameter exists, false (0) otherwise\&. This applies only for threads that have been created via \fBthread::create\fR command\&. .TP \fBthread::send\fR ?-async? ?-head? \fIid\fR \fIscript\fR ?varname? This command passes a \fIscript\fR to another thread and, optionally, waits for the result\&. If the \fB-async\fR flag is specified, the command does not wait for the result and it returns empty string\&. The target thread must enter it's event loop in order to receive scripts sent via this command\&. This is done by default for threads created without a startup script\&. Threads can enter the event loop explicitly by calling \fBthread::wait\fR or any other relevant Tcl/Tk command, like \fBupdate\fR, \fBvwait\fR, etc\&. .sp Optional \fBvarname\fR specifies name of the variable to store the result of the \fIscript\fR\&. Without the \fB-async\fR flag, the command returns the evaluation code, similarily to the standard Tcl \fBcatch\fR command\&. If, however, the \fB-async\fR flag is specified, the command returns immediately and caller can later \fBvwait\fR on ?varname? to get the result of the passed \fIscript\fR .CS set t1 [thread::create] set t2 [thread::create] thread::send -async $t1 "set a 1" result thread::send -async $t2 "set b 2" result for {set i 0} {$i < 2} {incr i} { vwait result } .CE .IP In the above example, two threads were fed work and both of them were instructed to signalize the same variable "result" in the calling thread\&. The caller entered the event loop twice to get both results\&. Note, however, that the order of the received results may vary, depending on the current system load, type of work done, etc, etc\&. .sp Many threads can simultaneously send scripts to the target thread for execution\&. All of them are entered into the event queue of the target thread and executed on the FIFO basis, intermingled with optional other events pending in the event queue of the target thread\&. Using the optional ?-head? switch, scripts posted to the thread's event queue can be placed on the head, instead on the tail of the queue, thus being executed in the LIFO fashion\&. .TP \fBthread::broadcast\fR \fIscript\fR This command passes a \fIscript\fR to all threads created by the package for execution\&. It does not wait for response from any of the threads\&. .TP \fBthread::wait\fR This enters the event loop so a thread can receive messages from the \fBthread::send\fR command\&. This command should only be used within the script passed to the \fBthread::create\fR\&. It should be the very last command in the script\&. If this is not the case, the exiting thread will continue executing the script lines past the \fBthread::wait\fR which is usually not what you want and/or expect\&. .CS set t1 [thread::create { # # Do some initialization work here # thread::wait ; # Enter the event loop }] .CE .TP \fBthread::eval\fR ?-lock mutex? \fIarg\fR ?arg \&.\&.\&.? This command concatenates passed arguments and evaluates the resulting script under the mutex protection\&. If no mutex is specified by using the ?-lock mutex? optional argument, the internal static mutex is used\&. .TP \fBthread::join\fR \fIid\fR This command waits for the thread with ID \fIid\fR to exit and then returns it's exit code\&. Errors will be returned for threads which are not joinable or already waited upon by another thread\&. Upon the join the handle of the thread has gone out of scope and should not be used any more\&. .TP \fBthread::configure\fR \fIid\fR ?option? ?value? ?\&.\&.\&.? This command configures various low-level aspects of the thread with ID \fIid\fR in the similar way as the standard Tcl command \fBfconfigure\fR configures some Tcl channel options\&. Options currently supported are: \fB-eventmark\fR and \fB-unwindonerror\fR\&. .sp The \fB-eventmark\fR option, when set, limits the number of asynchronously posted scripts to the thread event loop\&. The \fBthread::send -async\fR command will block until the number of pending scripts in the event loop does not drop below the value configured with \fB-eventmark\fR\&. Default value for the \fB-eventmark\fR is 0 (zero) which effectively disables the checking, i\&.e\&. allows for unlimited number of posted scripts\&. .sp The \fB-unwindonerror\fR option, when set, causes the target thread to unwind if the result of the script processing resulted in error\&. Default value for the \fB-unwindonerror\fR is 0 (false), i\&.e\&. thread continues to process scripts after one of the posted scripts fails\&. .TP \fBthread::transfer\fR \fIid\fR \fIchannel\fR This moves the specified \fIchannel\fR from the current thread and interpreter to the main interpreter of the thread with the given \fIid\fR\&. After the move the current interpreter has no access to the channel any more, but the main interpreter of the target thread will be able to use it from now on\&. The command waits until the other thread has incorporated the channel\&. Because of this it is possible to deadlock the participating threads by commanding the other through a synchronous \fBthread::send\fR to transfer a channel to us\&. This easily extends into longer loops of threads waiting for each other\&. Other restrictions: the channel in question must not be shared among multiple interpreters running in the sending thread\&. This automatically excludes the special channels for standard input, output and error\&. .sp Due to the internal Tcl core implementation and the restriction on transferring shared channels, one has to take extra measures when transferring socket channels created by accepting the connection out of the \fBsocket\fR commands callback procedures: .CS socket -server _Accept 2200 proc _Accept {s ipaddr port} { after idle [list Accept $s $ipaddr $port] } proc Accept {s ipaddr port} { set tid [thread::create] thread::transfer $tid $s } .CE .TP \fBthread::detach\fR \fIchannel\fR This detaches the specified \fIchannel\fR from the current thread and interpreter\&. After that, the current interpreter has no access to the channel any more\&. The channel is in the parked state until some other (or the same) thread attaches the channel again with \fBthread::attach\fR\&. Restrictions: same as for transferring shared channels with the \fBthread::transfer\fR command\&. .TP \fBthread::attach\fR \fIchannel\fR This attaches the previously detached \fIchannel\fR in the current thread/interpreter\&. For already existing channels, the command does nothing, i\&.e\&. it is not an error to attach the same channel more than once\&. The first operation will actualy perform the operation, while all subsequent operation will just do nothing\&. Command throws error if the \fIchannel\fR cannot be found in the list of detached channels and/or in the current interpreter\&. .TP \fBthread::mutex\fR Mutexes are most common thread synchronization primitives\&. They are used to synchronize access from two or more threads to one or more shared resources\&. This command provides script-level access to exclusive and/or recursive mutexes\&. Exclusive mutexes can be locked only once by one thread, while recursive mutexes can be locked many times by the same thread\&. For recursive mutexes, number of lock and unlock operations must match, otherwise, the mutex will never be released, which would lead to various deadlock situations\&. .sp Care has to be taken when using mutexes in an multithreading program\&. Improper use of mutexes may lead to various deadlock situations, especially when using exclusive mutexes\&. .sp The \fBthread::mutex\fR command supports following subcommands and options: .RS .TP \fBthread::mutex\fR \fBcreate\fR ?-recursive? Creates the mutex and returns it's opaque handle\&. This handle should be used for any future reference to the newly created mutex\&. If no optional ?-recursive? argument was specified, the command creates the exclusive mutex\&. With the ?-recursive? argument, the command creates a recursive mutex\&. .TP \fBthread::mutex\fR \fBdestroy\fR \fImutex\fR Destroys the \fImutex\fR\&. Mutex should be in unlocked state before the destroy attempt\&. If the mutex is locked, the command will throw Tcl error\&. .TP \fBthread::mutex\fR \fBlock\fR \fImutex\fR Locks the \fImutex\fR\&. Locking the exclusive mutex may throw Tcl error if on attempt to lock the same mutex twice from the same thread\&. If your program logic forces you to lock the same mutex twice or more from the same thread (this may happen in recursive procedure invocations) you should consider using the recursive mutexes\&. .TP \fBthread::mutex\fR \fBunlock\fR \fImutex\fR Unlocks the \fImutex\fR so some other thread may lock it again\&. Attempt to unlock the already unlocked mutex will throw Tcl error\&. .RE .sp .TP \fBthread::rwmutex\fR This command creates many-readers/single-writer mutexes\&. Reader/writer mutexes allow you to serialize access to a shared resource more optimally\&. In situations where a shared resource gets mostly read and seldom modified, you might gain some performace by using reader/writer mutexes instead of exclusive or recursive mutexes\&. .sp For reading the resource, thread should obtain a read lock on the resource\&. Read lock is non-exclusive, meaning that more than one thread can obtain a read lock to the same resource, without waiting on other readers\&. For changing the resource, however, a thread must obtain a exclusive write lock\&. This lock effectively blocks all threads from gaining the read-lock while the resource is been modified by the writer thread\&. Only after the write lock has been released, the resource may be read-locked again\&. .sp The \fBthread::rwmutex\fR command supports following subcommands and options: .RS .TP \fBthread::rwmutex\fR \fBcreate\fR Creates the reader/writer mutex and returns it's opaque handle\&. This handle should be used for any future reference to the newly created mutex\&. .TP \fBthread::rwmutex\fR \fBdestroy\fR \fImutex\fR Destroys the reader/writer \fImutex\fR\&. If the mutex is already locked, attempt to destroy it will throw Tcl error\&. .TP \fBthread::rwmutex\fR \fBrlock\fR \fImutex\fR Locks the \fImutex\fR for reading\&. More than one thread may read-lock the same \fImutex\fR at the same time\&. .TP \fBthread::rwmutex\fR \fBwlock\fR \fImutex\fR Locks the \fImutex\fR for writing\&. Only one thread may write-lock the same \fImutex\fR at the same time\&. Attempt to write-lock same \fImutex\fR twice from the same thread will throw Tcl error\&. .TP \fBthread::rwmutex\fR \fBunlock\fR \fImutex\fR Unlocks the \fImutex\fR so some other thread may lock it again\&. Attempt to unlock already unlocked \fImutex\fR will throw Tcl error\&. .RE .sp .TP \fBthread::cond\fR This command provides script-level access to condition variables\&. A condition variable creates a safe environment for the program to test some condition, sleep on it when false and be awakened when it might have become true\&. A condition variable is always used in the conjuction with an exclusive mutex\&. If you attempt to use other type of mutex in conjuction with the condition variable, a Tcl error will be thrown\&. .sp The command supports following subcommands and options: .RS .TP \fBthread::cond\fR \fBcreate\fR Creates the condition variable and returns it's opaque handle\&. This handle should be used for any future reference to newly created condition variable\&. .TP \fBthread::cond\fR \fBdestroy\fR \fIcond\fR Destroys condition variable \fIcond\fR\&. Extreme care has to be taken that nobody is using (i\&.e\&. waiting on) the condition variable, otherwise unexpected errors may happen\&. .TP \fBthread::cond\fR \fBnotify\fR \fIcond\fR Wakes up all threads waiting on the condition variable \fIcond\fR\&. .TP \fBthread::cond\fR \fBwait\fR \fIcond\fR \fImutex\fR ?ms? This command is used to suspend program execution until the condition variable \fIcond\fR has been signalled or the optional timer has expired\&. The exclusive \fImutex\fR must be locked by the calling thread on entrance to this command\&. If the mutex is not locked, Tcl error is thrown\&. While waiting on the \fIcond\fR, the command releases \fImutex\fR\&. Before returning to the calling thread, the command re-acquires the \fImutex\fR again\&. Unlocking the \fImutex\fR and waiting on the condition variable \fIcond\fR is done atomically\&. .sp The \fBms\fR command option, if given, must be an integer specifying time interval in milliseconds the command waits to be signalled\&. Otherwise the command waits on condition notify forever\&. .sp In multithreading programs, there are many situations where a thread has to wait for some event to happen until it is allowed to proceed\&. This is usually accomplished by repeatedly testing a condition under the mutex protection and waiting on the condition variable until the condition evaluates to true: .CS set mutex [thread::mutex create] set cond [thread::cond create] thread::mutex lock $mutex while {<some_condition_is_true>} { thread::cond wait $cond $mutex } # Do some work under mutex protection thread::mutex unlock $mutex .CE .IP Repeated testing of the condition is needed since the condition variable may get signalled without the condition being actually changed (spurious thread wake-ups, for example)\&. .RE .PP .SH DISCUSSION The fundamental threading model in Tcl is that there can be one or more Tcl interpreters per thread, but each Tcl interpreter should only be used by a single thread which created it\&. A "shared memory" abstraction is awkward to provide in Tcl because Tcl makes assumptions about variable and data ownership\&. Therefore this extension supports a simple form of threading where the main thread can manage several background, or "worker" threads\&. For example, an event-driven server can pass requests to worker threads, and then await responses from worker threads or new client requests\&. Everything goes through the common Tcl event loop, so message passing between threads works naturally with event-driven I/O, \fBvwait\fR on variables, and so forth\&. For the transfer of bulk information it is possible to move channels between the threads\&. .PP For advanced multithreading scripts, script-level access to two basic synchronization primitives, mutex and condition variables, is also supported\&. .SH "SEE ALSO" \fIhttp://www\&.tcl\&.tk/doc/howto/thread_model\&.html\fR, tpool, tsv, ttrace .SH KEYWORDS events, message passing, mutex, synchronization, thread |
Changes to doc/man/tpool.n.
1 2 3 | '\" '\" Generated from file '' by tcllib/doctools with format 'nroff' '\" | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > | < < < < < < < | | | | | | | | > > > > > > > > > | < < < < < < < < | | | | | | | | | > > > > > > > | | | | | | | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | '\" '\" Generated from file '' by tcllib/doctools with format 'nroff' '\" .TH "tpool" n 2\&.8 "Tcl Threading" .\" The -*- nroff -*- definitions below are for supplemental macros used .\" in Tcl/Tk manual entries. .\" .\" .AP type name in/out ?indent? .\" Start paragraph describing an argument to a library procedure. .\" type is type of argument (int, etc.), in/out is either "in", "out", .\" or "in/out" to describe whether procedure reads or modifies arg, .\" and indent is equivalent to second arg of .IP (shouldn't ever be .\" needed; use .AS below instead) .\" .\" .AS ?type? ?name? .\" Give maximum sizes of arguments for setting tab stops. Type and .\" name are examples of largest possible arguments that will be passed .\" to .AP later. If args are omitted, default tab stops are used. .\" .\" .BS .\" Start box enclosure. From here until next .BE, everything will be .\" enclosed in one large box. .\" .\" .BE .\" End of box enclosure. .\" .\" .CS .\" Begin code excerpt. .\" .\" .CE .\" End code excerpt. .\" .\" .VS ?version? ?br? .\" Begin vertical sidebar, for use in marking newly-changed parts .\" of man pages. The first argument is ignored and used for recording .\" the version when the .VS was added, so that the sidebars can be .\" found and removed when they reach a certain age. If another argument .\" is present, then a line break is forced before starting the sidebar. .\" .\" .VE .\" End of vertical sidebar. .\" .\" .DS .\" Begin an indented unfilled display. .\" .\" .DE .\" End of indented unfilled display. .\" .\" .SO ?manpage? .\" Start of list of standard options for a Tk widget. The manpage .\" argument defines where to look up the standard options; if .\" omitted, defaults to "options". The options follow on successive .\" lines, in three columns separated by tabs. .\" .\" .SE .\" End of list of standard options for a Tk widget. .\" .\" .OP cmdName dbName dbClass .\" Start of description of a specific option. cmdName gives the .\" option's name as specified in the class command, dbName gives .\" the option's name in the option database, and dbClass gives .\" the option's class in the option database. .\" .\" .UL arg1 arg2 .\" Print arg1 underlined, then print arg2 normally. .\" .\" .QW arg1 ?arg2? .\" Print arg1 in quotes, then arg2 normally (for trailing punctuation). .\" .\" .PQ arg1 ?arg2? .\" Print an open parenthesis, arg1 in quotes, then arg2 normally .\" (for trailing punctuation) and then a closing parenthesis. .\" .\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages. .if t .wh -1.3i ^B .nr ^l \n(.l .ad b .\" # Start an argument description .de AP .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} .ta \\n()Au \\n()Bu .ie !"\\$3"" \{\ \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br .ie !"\\$2"" \{\ \&\\$1 \\fI\\$2\\fP .\} .el \{\ \&\\fI\\$1\\fP .\} .\} .. .\" # define tabbing values for .AP .de AS .nr )A 10n .if !"\\$1"" .nr )A \\w'\\$1'u+3n .nr )B \\n()Au+15n .\" .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n .nr )C \\n()Bu+\\w'(in/out)'u+2n .. .AS Tcl_Interp Tcl_CreateInterp in/out .\" # BS - start boxed text .\" # ^y = starting y location .\" # ^b = 1 .de BS .br .mk ^y .nr ^b 1u .if n .nf .if n .ti 0 .if n \l'\\n(.lu\(ul' .if n .fi .. .\" # BE - end boxed text (draw box now) .de BE .nf .ti 0 .mk ^t .ie n \l'\\n(^lu\(ul' .el \{\ .\" Draw four-sided box normally, but don't draw top of .\" box if the box started on an earlier page. .ie !\\n(^b-1 \{\ \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .el \}\ \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .\} .fi .br .nr ^b 0 .. .\" # VS - start vertical sidebar .\" # ^Y = starting y location .\" # ^v = 1 (for troff; for nroff this doesn't matter) .de VS .if !"\\$2"" .br .mk ^Y .ie n 'mc \s12\(br\s0 .el .nr ^v 1u .. .\" # VE - end of vertical sidebar .de VE .ie n 'mc .el \{\ .ev 2 .nf .ti 0 .mk ^t \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' .sp -1 .fi .ev .\} .nr ^v 0 .. .\" # Special macro to handle page bottom: finish off current .\" # box/sidebar if in box/sidebar mode, then invoked standard .\" # page bottom macro. .de ^B .ev 2 'ti 0 'nf .mk ^t .if \\n(^b \{\ .\" Draw three-sided box if this is the box's first page, |
︙ | ︙ | |||
180 181 182 183 184 185 186 | .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. | | | | > > | | | | < | < > | > > > > > > > > > > > > > > > > > > > | > | < | | | | > > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > > > > > > > > > > > | | | | | | | | | | | | | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 | .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. .\" # DS - begin display .de DS .RS .nf .sp .. .\" # DE - end display .de DE .fi .RE .sp .. .\" # SO - start of list of standard options .de SO 'ie '\\$1'' .ds So \\fBoptions\\fR 'el .ds So \\fB\\$1\\fR .SH "STANDARD OPTIONS" .LP .nf .ta 5.5c 11c .ft B .. .\" # SE - end of list of standard options .de SE .fi .ft R .LP See the \\*(So manual entry for details on the standard options. .. .\" # OP - start of full description for a single option .de OP .LP .nf .ta 4c Command-Line Name: \\fB\\$1\\fR Database Name: \\fB\\$2\\fR Database Class: \\fB\\$3\\fR .fi .IP .. .\" # CS - begin code excerpt .de CS .RS .nf .ta .25i .5i .75i 1i .. .\" # CE - end code excerpt .de CE .fi .RE .. .\" # UL - underline word .de UL \\$1\l'|0\(ul'\\$2 .. .\" # QW - apply quotation marks to word .de QW .ie '\\*(lq'"' ``\\$1''\\$2 .\"" fix emacs highlighting .el \\*(lq\\$1\\*(rq\\$2 .. .\" # PQ - apply parens and quotation marks to word .de PQ .ie '\\*(lq'"' (``\\$1''\\$2)\\$3 .\"" fix emacs highlighting .el (\\*(lq\\$1\\*(rq\\$2)\\$3 .. .\" # QR - quoted range .de QR .ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3 .\"" fix emacs highlighting .el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3 .. .\" # MT - "empty" string .de MT .QW "" .. .BS .SH NAME tpool \- Part of the Tcl threading extension implementing pools of worker threads\&. .SH SYNOPSIS package require \fBTcl 8\&.4\fR .sp package require \fBThread ?2\&.8?\fR .sp \fBtpool::create\fR ?options? .sp \fBtpool::names\fR .sp \fBtpool::post\fR ?-detached? ?-nowait? \fItpool\fR \fIscript\fR .sp \fBtpool::wait\fR \fItpool\fR \fIjoblist\fR ?varname? .sp \fBtpool::cancel\fR \fItpool\fR \fIjoblist\fR ?varname? .sp \fBtpool::get\fR \fItpool\fR \fIjob\fR .sp \fBtpool::preserve\fR \fItpool\fR .sp \fBtpool::release\fR \fItpool\fR .sp \fBtpool::suspend\fR \fItpool\fR .sp \fBtpool::resume\fR \fItpool\fR .sp .BE .SH DESCRIPTION This package creates and manages pools of worker threads\&. It allows you to post jobs to worker threads and wait for their completion\&. The threadpool implementation is Tcl event-loop aware\&. That means that any time a caller is forced to wait for an event (job being completed or a worker thread becoming idle or initialized), the implementation will enter the event loop and allow for servicing of other pending file or timer (or any other supported) events\&. .SH COMMANDS .TP \fBtpool::create\fR ?options? This command creates new threadpool\&. It accepts several options as key-value pairs\&. Options are used to tune some threadpool parameters\&. The command returns the ID of the newly created threadpool\&. .sp Following options are supported: .RS .TP \fB-minworkers\fR \fInumber\fR Minimum number of worker threads needed for this threadpool instance\&. During threadpool creation, the implementation will create somany worker threads upfront and will keep at least number of them alive during the lifetime of the threadpool instance\&. Default value of this parameter is 0 (zero)\&. which means that a newly threadpool will have no worker threads initialy\&. All worker threads will be started on demand by callers running \fBtpool::post\fR command and posting jobs to the job queue\&. .TP \fB-maxworkers\fR \fInumber\fR Maximum number of worker threads allowed for this threadpool instance\&. If a new job is pending and there are no idle worker threads available, the implementation will try to create new worker thread\&. If the number of available worker threads is lower than the given number, new worker thread will start\&. The caller will automatically enter the event loop and wait until the worker thread has initialized\&. If\&. however, the number of available worker threads is equal to the given number, the caller will enter the event loop and wait for the first worker thread to get idle, thus ready to run the job\&. Default value of this parameter is 4 (four), which means that the threadpool instance will allow maximum of 4 worker threads running jobs or being idle waiting for new jobs to get posted to the job queue\&. .TP \fB-idletime\fR \fIseconds\fR Time in seconds an idle worker thread waits for the job to get posted to the job queue\&. If no job arrives during this interval and the time expires, the worker thread will check the number of currently available worker threads and if the number is higher than the number set by the \fBminthreads\fR option, it will exit\&. If an \fBexitscript\fR has been defined, the exiting worker thread will first run the script and then exit\&. Errors from the exit script, if any, are ignored\&. .sp The idle worker thread is not servicing the event loop\&. If you, however, put the worker thread into the event loop, by evaluating the \fBvwait\fR or other related Tcl commands, the worker thread will not be in the idle state, hence the idle timer will not be taken into account\&. Default value for this option is unspecified\&. .TP \fB-initcmd\fR \fIscript\fR Sets a Tcl script used to initialize new worker thread\&. This is usually used to load packages and commands in the worker, set default variables, create namespaces, and such\&. If the passed script runs into a Tcl error, the worker will not be created and the initiating command (either the \fBtpool::create\fR or \fBtpool::post\fR) will throw error\&. Default value for this option is unspecified, hence, the Tcl interpreter of the worker thread will contain just the initial set of Tcl commands\&. .TP \fB-exitcmd\fR \fIscript\fR Sets a Tcl script run when the idle worker thread exits\&. This is normaly used to cleanup the state of the worker thread, release reserved resources, cleanup memory and such\&. Default value for this option is unspecified, thus no Tcl script will run on the worker thread exit\&. .RE .sp .TP \fBtpool::names\fR This command returns a list of IDs of threadpools created with the \fBtpool::create\fR command\&. If no threadpools were found, the command will return empty list\&. .TP \fBtpool::post\fR ?-detached? ?-nowait? \fItpool\fR \fIscript\fR This command sends a \fIscript\fR to the target \fItpool\fR threadpool for execution\&. The script will be executed in the first available idle worker thread\&. If there are no idle worker threads available, the command will create new one, enter the event loop and service events until the newly created thread is initialized\&. If the current number of worker threads is equal to the maximum number of worker threads, as defined during the threadpool creation, the command will enter the event loop and service events while waiting for one of the worker threads to become idle\&. If the optional ?-nowait? argument is given, the command will not wait for one idle worker\&. It will just place the job in the pool's job queue and return immediately\&. .sp The command returns the ID of the posted job\&. This ID is used for subsequent \fBtpool::wait\fR, \fBtpool::get\fR and \fBtpool::cancel\fR commands to wait for and retrieve result of the posted script, or cancel the posted job respectively\&. If the optional ?-detached? argument is specified, the command will post a detached job\&. A detached job can not be cancelled or waited upon and is not identified by the job ID\&. .sp If the threadpool \fItpool\fR is not found in the list of active thread pools, the command will throw error\&. The error will also be triggered if the newly created worker thread fails to initialize\&. .TP \fBtpool::wait\fR \fItpool\fR \fIjoblist\fR ?varname? This command waits for one or many jobs, whose job IDs are given in the \fIjoblist\fR to get processed by the worker thread(s)\&. If none of the specified jobs are ready, the command will enter the event loop, service events and wait for the first job to get ready\&. .sp The command returns the list of completed job IDs\&. If the optional variable ?varname? is given, it will be set to the list of jobs in the \fIjoblist\fR which are still pending\&. If the threadpool \fItpool\fR is not found in the list of active thread pools, the command will throw error\&. .TP \fBtpool::cancel\fR \fItpool\fR \fIjoblist\fR ?varname? This command cancels the previously posted jobs given by the \fIjoblist\fR to the pool \fItpool\fR\&. Job cancellation succeeds only for job still waiting to be processed\&. If the job is already being executed by one of the worker threads, the job will not be cancelled\&. The command returns the list of cancelled job IDs\&. If the optional variable ?varname? is given, it will be set to the list of jobs in the \fIjoblist\fR which were not cancelled\&. If the threadpool \fItpool\fR is not found in the list of active thread pools, the command will throw error\&. .TP \fBtpool::get\fR \fItpool\fR \fIjob\fR This command retrieves the result of the previously posted \fIjob\fR\&. Only results of jobs waited upon with the \fBtpool::wait\fR command can be retrieved\&. If the execution of the script resulted in error, the command will throw the error and update the \fBerrorInfo\fR and \fBerrorCode\fR variables correspondingly\&. If the pool \fItpool\fR is not found in the list of threadpools, the command will throw error\&. If the job \fIjob\fR is not ready for retrieval, because it is currently being executed by the worker thread, the command will throw error\&. .TP \fBtpool::preserve\fR \fItpool\fR Each call to this command increments the reference counter of the threadpool \fItpool\fR by one (1)\&. Command returns the value of the reference counter after the increment\&. By incrementing the reference counter, the caller signalizes that he/she wishes to use the resource for a longer period of time\&. .TP \fBtpool::release\fR \fItpool\fR Each call to this command decrements the reference counter of the threadpool \fItpool\fR by one (1)\&.Command returns the value of the reference counter after the decrement\&. When the reference counter reaches zero (0), the threadpool \fItpool\fR is marked for termination\&. You should not reference the threadpool after the \fBtpool::release\fR command returns zero\&. The \fItpool\fR handle goes out of scope and should not be used any more\&. Any following reference to the same threadpool handle will result in Tcl error\&. .TP \fBtpool::suspend\fR \fItpool\fR Suspends processing work on this queue\&. All pool workers are paused but additional work can be added to the pool\&. Note that adding the additional work will not increase the number of workers dynamically as the pool processing is suspended\&. Number of workers is maintained to the count that was found prior suspending worker activity\&. If you need to assure certain number of worker threads, use the \fBminworkers\fR option of the \fBtpool::create\fR command\&. .TP \fBtpool::resume\fR \fItpool\fR Resume processing work on this queue\&. All paused (suspended) workers are free to get work from the pool\&. Note that resuming pool operation will just let already created workers to proceed\&. It will not create additional worker threads to handle the work posted to the pool's work queue\&. .PP .SH DISCUSSION Threadpool is one of the most common threading paradigm when it comes to server applications handling a large number of relatively small tasks\&. A very simplistic model for building a server application would be to create a new thread each time a request arrives and service the request in the new thread\&. One of the disadvantages of this approach is that the overhead of creating a new thread for each request is significant; a server that created a new thread for each request would spend more time and consume more system resources in creating and destroying threads than in processing actual user requests\&. In addition to the overhead of creating and destroying threads, active threads consume system resources\&. Creating too many threads can cause the system to run out of memory or trash due to excessive memory consumption\&. .PP A thread pool offers a solution to both the problem of thread life-cycle overhead and the problem of resource trashing\&. By reusing threads for multiple tasks, the thread-creation overhead is spread over many tasks\&. As a bonus, because the thread already exists when a request arrives, the delay introduced by thread creation is eliminated\&. Thus, the request can be serviced immediately\&. Furthermore, by properly tuning the number of threads in the thread pool, resource thrashing may also be eliminated by forcing any request to wait until a thread is available to process it\&. .SH "SEE ALSO" thread, tsv, ttrace .SH KEYWORDS thread, threadpool |
Changes to doc/man/tsv.n.
1 2 3 | '\" '\" Generated from file '' by tcllib/doctools with format 'nroff' '\" | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > | < < < < < < < | | | | | | | | > > > > > > > > > | < < < < < < < < | | | | | | | | | > > > > > > > | | | | | | | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | '\" '\" Generated from file '' by tcllib/doctools with format 'nroff' '\" .TH "tsv" n 2\&.8 "Tcl Threading" .\" The -*- nroff -*- definitions below are for supplemental macros used .\" in Tcl/Tk manual entries. .\" .\" .AP type name in/out ?indent? .\" Start paragraph describing an argument to a library procedure. .\" type is type of argument (int, etc.), in/out is either "in", "out", .\" or "in/out" to describe whether procedure reads or modifies arg, .\" and indent is equivalent to second arg of .IP (shouldn't ever be .\" needed; use .AS below instead) .\" .\" .AS ?type? ?name? .\" Give maximum sizes of arguments for setting tab stops. Type and .\" name are examples of largest possible arguments that will be passed .\" to .AP later. If args are omitted, default tab stops are used. .\" .\" .BS .\" Start box enclosure. From here until next .BE, everything will be .\" enclosed in one large box. .\" .\" .BE .\" End of box enclosure. .\" .\" .CS .\" Begin code excerpt. .\" .\" .CE .\" End code excerpt. .\" .\" .VS ?version? ?br? .\" Begin vertical sidebar, for use in marking newly-changed parts .\" of man pages. The first argument is ignored and used for recording .\" the version when the .VS was added, so that the sidebars can be .\" found and removed when they reach a certain age. If another argument .\" is present, then a line break is forced before starting the sidebar. .\" .\" .VE .\" End of vertical sidebar. .\" .\" .DS .\" Begin an indented unfilled display. .\" .\" .DE .\" End of indented unfilled display. .\" .\" .SO ?manpage? .\" Start of list of standard options for a Tk widget. The manpage .\" argument defines where to look up the standard options; if .\" omitted, defaults to "options". The options follow on successive .\" lines, in three columns separated by tabs. .\" .\" .SE .\" End of list of standard options for a Tk widget. .\" .\" .OP cmdName dbName dbClass .\" Start of description of a specific option. cmdName gives the .\" option's name as specified in the class command, dbName gives .\" the option's name in the option database, and dbClass gives .\" the option's class in the option database. .\" .\" .UL arg1 arg2 .\" Print arg1 underlined, then print arg2 normally. .\" .\" .QW arg1 ?arg2? .\" Print arg1 in quotes, then arg2 normally (for trailing punctuation). .\" .\" .PQ arg1 ?arg2? .\" Print an open parenthesis, arg1 in quotes, then arg2 normally .\" (for trailing punctuation) and then a closing parenthesis. .\" .\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages. .if t .wh -1.3i ^B .nr ^l \n(.l .ad b .\" # Start an argument description .de AP .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} .ta \\n()Au \\n()Bu .ie !"\\$3"" \{\ \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br .ie !"\\$2"" \{\ \&\\$1 \\fI\\$2\\fP .\} .el \{\ \&\\fI\\$1\\fP .\} .\} .. .\" # define tabbing values for .AP .de AS .nr )A 10n .if !"\\$1"" .nr )A \\w'\\$1'u+3n .nr )B \\n()Au+15n .\" .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n .nr )C \\n()Bu+\\w'(in/out)'u+2n .. .AS Tcl_Interp Tcl_CreateInterp in/out .\" # BS - start boxed text .\" # ^y = starting y location .\" # ^b = 1 .de BS .br .mk ^y .nr ^b 1u .if n .nf .if n .ti 0 .if n \l'\\n(.lu\(ul' .if n .fi .. .\" # BE - end boxed text (draw box now) .de BE .nf .ti 0 .mk ^t .ie n \l'\\n(^lu\(ul' .el \{\ .\" Draw four-sided box normally, but don't draw top of .\" box if the box started on an earlier page. .ie !\\n(^b-1 \{\ \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .el \}\ \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .\} .fi .br .nr ^b 0 .. .\" # VS - start vertical sidebar .\" # ^Y = starting y location .\" # ^v = 1 (for troff; for nroff this doesn't matter) .de VS .if !"\\$2"" .br .mk ^Y .ie n 'mc \s12\(br\s0 .el .nr ^v 1u .. .\" # VE - end of vertical sidebar .de VE .ie n 'mc .el \{\ .ev 2 .nf .ti 0 .mk ^t \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' .sp -1 .fi .ev .\} .nr ^v 0 .. .\" # Special macro to handle page bottom: finish off current .\" # box/sidebar if in box/sidebar mode, then invoked standard .\" # page bottom macro. .de ^B .ev 2 'ti 0 'nf .mk ^t .if \\n(^b \{\ .\" Draw three-sided box if this is the box's first page, |
︙ | ︙ | |||
180 181 182 183 184 185 186 | .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. | | | | > > | | | | < | < > | > > > > > > > > > > > > > > > > > > > | > | < | < | | | | | > > | | | | | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. .\" # DS - begin display .de DS .RS .nf .sp .. .\" # DE - end display .de DE .fi .RE .sp .. .\" # SO - start of list of standard options .de SO 'ie '\\$1'' .ds So \\fBoptions\\fR 'el .ds So \\fB\\$1\\fR .SH "STANDARD OPTIONS" .LP .nf .ta 5.5c 11c .ft B .. .\" # SE - end of list of standard options .de SE .fi .ft R .LP See the \\*(So manual entry for details on the standard options. .. .\" # OP - start of full description for a single option .de OP .LP .nf .ta 4c Command-Line Name: \\fB\\$1\\fR Database Name: \\fB\\$2\\fR Database Class: \\fB\\$3\\fR .fi .IP .. .\" # CS - begin code excerpt .de CS .RS .nf .ta .25i .5i .75i 1i .. .\" # CE - end code excerpt .de CE .fi .RE .. .\" # UL - underline word .de UL \\$1\l'|0\(ul'\\$2 .. .\" # QW - apply quotation marks to word .de QW .ie '\\*(lq'"' ``\\$1''\\$2 .\"" fix emacs highlighting .el \\*(lq\\$1\\*(rq\\$2 .. .\" # PQ - apply parens and quotation marks to word .de PQ .ie '\\*(lq'"' (``\\$1''\\$2)\\$3 .\"" fix emacs highlighting .el (\\*(lq\\$1\\*(rq\\$2)\\$3 .. .\" # QR - quoted range .de QR .ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3 .\"" fix emacs highlighting .el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3 .. .\" # MT - "empty" string .de MT .QW "" .. .BS .SH NAME tsv \- Part of the Tcl threading extension allowing script level manipulation of data shared between threads\&. .SH SYNOPSIS package require \fBTcl 8\&.4\fR .sp package require \fBThread ?2\&.8?\fR .sp \fBtsv::names\fR ?pattern? .sp \fBtsv::object\fR \fIvarname\fR \fIelement\fR .sp \fBtsv::set\fR \fIvarname\fR \fIelement\fR ?value? .sp \fBtsv::get\fR \fIvarname\fR \fIelement\fR ?namedvar? .sp \fBtsv::unset\fR \fIvarname\fR ?element? .sp \fBtsv::exists\fR \fIvarname\fR \fIelement\fR .sp \fBtsv::pop\fR \fIvarname\fR \fIelement\fR .sp \fBtsv::move\fR \fIvarname\fR \fIoldname\fR \fInewname\fR .sp \fBtsv::incr\fR \fIvarname\fR \fIelement\fR ?count? .sp \fBtsv::append\fR \fIvarname\fR \fIelement\fR \fIvalue\fR ?value \&.\&.\&.? .sp \fBtsv::lock\fR \fIvarname\fR \fIarg\fR ?arg \&.\&.\&.? .sp \fBtsv::handlers\fR .sp \fBtsv::lappend\fR \fIvarname\fR \fIelement\fR \fIvalue\fR ?value \&.\&.\&.? .sp \fBtsv::linsert\fR \fIvarname\fR \fIelement\fR \fIindex\fR \fIvalue\fR ?value \&.\&.\&.? .sp \fBtsv::lreplace\fR \fIvarname\fR \fIelement\fR \fIfirst\fR \fIlast\fR ?value \&.\&.\&.? .sp \fBtsv::llength\fR \fIvarname\fR \fIelement\fR .sp \fBtsv::lindex\fR \fIvarname\fR \fIelement\fR ?index? .sp \fBtsv::lrange\fR \fIvarname\fR \fIelement\fR \fIfrom\fR \fIto\fR .sp \fBtsv::lsearch\fR \fIvarname\fR \fIelement\fR ?options? \fIpattern\fR .sp \fBtsv::lset\fR \fIvarname\fR \fIelement\fR \fIindex\fR ?index \&.\&.\&.? \fIvalue\fR .sp \fBtsv::lpop\fR \fIvarname\fR \fIelement\fR ?index? .sp \fBtsv::lpush\fR \fIvarname\fR \fIelement\fR ?index? .sp \fBtsv::array set\fR \fIvarname\fR \fIlist\fR .sp |
︙ | ︙ | |||
310 311 312 313 314 315 316 | .sp \fBtsv::keyldel\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR .sp \fBtsv::keylget\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR ?retvar? .sp \fBtsv::keylkeys\fR \fIvarname\fR \fIkeylist\fR ?key? .sp | | | | | | | | | | | | | | > > | > | | | | | | | | | | | | | | | | | | | | | | | > > | > > > > > > | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | > | | | | | | | > > | > | | | | > > | > | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 | .sp \fBtsv::keyldel\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR .sp \fBtsv::keylget\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR ?retvar? .sp \fBtsv::keylkeys\fR \fIvarname\fR \fIkeylist\fR ?key? .sp \fBtsv::keylset\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR \fIvalue\fR ?key value\&.\&.? .sp .BE .SH DESCRIPTION This section describes commands implementing thread shared variables\&. A thread shared variable is very similar to a Tcl array but in contrast to a Tcl array it is created in shared memory and can be accessed from many threads at the same time\&. Important feature of thread shared variable is that each access to the variable is internaly protected by a mutex so script programmer does not have to take care about locking the variable himself\&. .PP Thread shared variables are not bound to any thread explicitly\&. That means that when a thread which created any of thread shared variables exits, the variable and associated memory is not unset/reclaimed\&. User has to explicitly unset the variable to reclaim the memory consumed by the variable\&. .SH "ELEMENT COMMANDS" .TP \fBtsv::names\fR ?pattern? Returns names of shared variables matching optional ?pattern? or all known variables if pattern is ommited\&. .TP \fBtsv::object\fR \fIvarname\fR \fIelement\fR Creates object accessor command for the \fIelement\fR in the shared variable \fIvarname\fR\&. Using this command, one can apply most of the other shared variable commands as method functions of the element object command\&. The object command is automatically deleted when the element which this command is pointing to is unset\&. .CS % tsv::set foo bar "A shared string" % set string [tsv::object foo bar] % $string append " appended" => A shared string appended .CE .TP \fBtsv::set\fR \fIvarname\fR \fIelement\fR ?value? Sets the value of the \fIelement\fR in the shared variable \fIvarname\fR to \fIvalue\fR and returns the value to caller\&. The \fIvalue\fR may be ommited, in which case the command will return the current value of the element\&. If the element cannot be found, error is triggered\&. .TP \fBtsv::get\fR \fIvarname\fR \fIelement\fR ?namedvar? Retrieves the value of the \fIelement\fR from the shared variable \fIvarname\fR\&. If the optional argument \fInamedvar\fR is given, the value is stored in the named variable\&. Return value of the command depends of the existence of the optional argument \fInamedvar\fR\&. If the argument is ommited and the requested element cannot be found in the shared array, the command triggers error\&. If, however, the optional argument is given on the command line, the command returns true (1) if the element is found or false (0) if the element is not found\&. .TP \fBtsv::unset\fR \fIvarname\fR ?element? Unsets the \fIelement\fR from the shared variable \fIvarname\fR\&. If the optional element is not given, it deletes the variable\&. .TP \fBtsv::exists\fR \fIvarname\fR \fIelement\fR Checks wether the \fIelement\fR exists in the shared variable \fIvarname\fR and returns true (1) if it does or false (0) if it doesn't\&. .TP \fBtsv::pop\fR \fIvarname\fR \fIelement\fR Returns value of the \fIelement\fR in the shared variable \fIvarname\fR and unsets the element, all in one atomic operation\&. .TP \fBtsv::move\fR \fIvarname\fR \fIoldname\fR \fInewname\fR Renames the element \fIoldname\fR to the \fInewname\fR in the shared variable \fIvarname\fR\&. This effectively performs an get/unset/set sequence of operations but all in one atomic step\&. .TP \fBtsv::incr\fR \fIvarname\fR \fIelement\fR ?count? Similar to standard Tcl \fBincr\fR command but increments the value of the \fIelement\fR in shared variaboe \fIvarname\fR instead of the Tcl variable\&. .TP \fBtsv::append\fR \fIvarname\fR \fIelement\fR \fIvalue\fR ?value \&.\&.\&.? Similar to standard Tcl \fBappend\fR command but appends one or more values to the \fIelement\fR in shared variable \fIvarname\fR instead of the Tcl variable\&. .TP \fBtsv::lock\fR \fIvarname\fR \fIarg\fR ?arg \&.\&.\&.? This command concatenates passed arguments and evaluates the resulting script under the internal mutex protection\&. During the script evaluation, the entire shared variable is locked\&. For shared variable commands within the script, internal locking is disabled so no deadlock can occur\&. It is also allowed to unset the shared variable from within the script\&. The shared variable is automatically created if it did not exists at the time of the first lock operation\&. .CS % tsv::lock foo { tsv::lappend foo bar 1 tsv::lappend foo bar 2 puts stderr [tsv::set foo bar] tsv::unset foo } .CE .TP \fBtsv::handlers\fR Returns the names of all persistent storage handlers enabled at compile time\&. See \fBARRAY COMMANDS\fR for details\&. .PP .SH "LIST COMMANDS" Those command are similar to the equivalently named Tcl command\&. The difference is that they operate on elements of shared arrays\&. .TP \fBtsv::lappend\fR \fIvarname\fR \fIelement\fR \fIvalue\fR ?value \&.\&.\&.? Similar to standard Tcl \fBlappend\fR command but appends one or more values to the \fIelement\fR in shared variable \fIvarname\fR instead of the Tcl variable\&. .TP \fBtsv::linsert\fR \fIvarname\fR \fIelement\fR \fIindex\fR \fIvalue\fR ?value \&.\&.\&.? Similar to standard Tcl \fBlinsert\fR command but inserts one or more values at the \fIindex\fR list position in the \fIelement\fR in the shared variable \fIvarname\fR instead of the Tcl variable\&. .TP \fBtsv::lreplace\fR \fIvarname\fR \fIelement\fR \fIfirst\fR \fIlast\fR ?value \&.\&.\&.? Similar to standard Tcl \fBlreplace\fR command but replaces one or more values between the \fIfirst\fR and \fIlast\fR position in the \fIelement\fR of the shared variable \fIvarname\fR instead of the Tcl variable\&. .TP \fBtsv::llength\fR \fIvarname\fR \fIelement\fR Similar to standard Tcl \fBllength\fR command but returns length of the \fIelement\fR in the shared variable \fIvarname\fR instead of the Tcl variable\&. .TP \fBtsv::lindex\fR \fIvarname\fR \fIelement\fR ?index? Similar to standard Tcl \fBlindex\fR command but returns the value at the \fIindex\fR list position of the \fIelement\fR from the shared variable \fIvarname\fR instead of the Tcl variable\&. .TP \fBtsv::lrange\fR \fIvarname\fR \fIelement\fR \fIfrom\fR \fIto\fR Similar to standard Tcl \fBlrange\fR command but returns values between \fIfrom\fR and \fIto\fR list positions from the \fIelement\fR in the shared variable \fIvarname\fR instead of the Tcl variable\&. .TP \fBtsv::lsearch\fR \fIvarname\fR \fIelement\fR ?options? \fIpattern\fR Similar to standard Tcl \fBlsearch\fR command but searches the \fIelement\fR in the shared variable \fIvarname\fR instead of the Tcl variable\&. .TP \fBtsv::lset\fR \fIvarname\fR \fIelement\fR \fIindex\fR ?index \&.\&.\&.? \fIvalue\fR Similar to standard Tcl \fBlset\fR command but sets the \fIelement\fR in the shared variable \fIvarname\fR instead of the Tcl variable\&. .TP \fBtsv::lpop\fR \fIvarname\fR \fIelement\fR ?index? Similar to the standard Tcl \fBlindex\fR command but in addition to returning, it also splices the value out of the \fIelement\fR from the shared variable \fIvarname\fR in one atomic operation\&. In contrast to the Tcl \fBlindex\fR command, this command returns no value to the caller\&. .TP \fBtsv::lpush\fR \fIvarname\fR \fIelement\fR ?index? This command performes the opposite of the \fBtsv::lpop\fR command\&. As its counterpart, it returns no value to the caller\&. .PP .SH "ARRAY COMMANDS" This command supports most of the options of the standard Tcl \fBarray\fR command\&. In addition to those, it allows binding a shared variable to some persisten storage databases\&. Currently the persistent options supported are the famous GNU Gdbm and LMDB\&. These options have to be selected during the package compilation time\&. The implementation provides hooks for defining other persistency layers, if needed\&. .TP \fBtsv::array set\fR \fIvarname\fR \fIlist\fR Does the same as standard Tcl \fBarray set\fR\&. .TP \fBtsv::array get\fR \fIvarname\fR ?pattern? Does the same as standard Tcl \fBarray get\fR\&. .TP \fBtsv::array names\fR \fIvarname\fR ?pattern? Does the same as standard Tcl \fBarray names\fR\&. .TP \fBtsv::array size\fR \fIvarname\fR Does the same as standard Tcl \fBarray size\fR\&. .TP \fBtsv::array reset\fR \fIvarname\fR \fIlist\fR Does the same as standard Tcl \fBarray set\fR but it clears the \fIvarname\fR and sets new values from the list atomically\&. .TP \fBtsv::array bind\fR \fIvarname\fR \fIhandle\fR Binds the \fIvarname\fR to the persistent storage \fIhandle\fR\&. The format of the \fIhandle\fR is <handler>:<address>, where <handler> is "gdbm" for GNU Gdbm and "lmdb" for LMDB and <address> is the path to the database file\&. .TP \fBtsv::array unbind\fR \fIvarname\fR Unbinds the shared \fIarray\fR from its bound persistent storage\&. .TP \fBtsv::array isbound\fR \fIvarname\fR Returns true (1) if the shared \fIvarname\fR is bound to some persistent storage or zero (0) if not\&. .PP .SH "KEYED LIST COMMANDS" Keyed list commands are borrowed from the TclX package\&. Keyed lists provide a structured data type built upon standard Tcl lists\&. This is a functionality similar to structs in the C programming language\&. .PP A keyed list is a list in which each element contains a key and value pair\&. These element pairs are stored as lists themselves, where the key is the first element of the list, and the value is the second\&. The key-value pairs are referred to as fields\&. This is an example of a keyed list: .CS {{NAME {Frank Zappa}} {JOB {musician and composer}}} .CE Fields may contain subfields; `\&.' is the separator character\&. Subfields are actually fields where the value is another keyed list\&. Thus the following list has the top level fields ID and NAME, and subfields NAME\&.FIRST and NAME\&.LAST: .CS {ID 106} {NAME {{FIRST Frank} {LAST Zappa}}} .CE There is no limit to the recursive depth of subfields, allowing one to build complex data structures\&. Keyed lists are constructed and accessed via a number of commands\&. All keyed list management commands take the name of the variable containing the keyed list as an argument (i\&.e\&. passed by reference), rather than passing the list directly\&. .TP \fBtsv::keyldel\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR Delete the field specified by \fIkey\fR from the keyed list \fIkeylist\fR in the shared variable \fIvarname\fR\&. This removes both the key and the value from the keyed list\&. .TP \fBtsv::keylget\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR ?retvar? Return the value associated with \fIkey\fR from the keyed list \fIkeylist\fR in the shared variable \fIvarname\fR\&. If the optional \fIretvar\fR is not specified, then the value will be returned as the result of the command\&. In this case, if key is not found in the list, an error will result\&. .sp If \fIretvar\fR is specified and \fIkey\fR is in the list, then the value is returned in the variable \fIretvar\fR and the command returns 1 if the key was present within the list\&. If \fIkey\fR isn't in the list, the command will return 0, and \fIretvar\fR will be left unchanged\&. If {} is specified for \fIretvar\fR, the value is not returned, allowing the Tcl programmer to determine if a \fIkey\fR is present in a keyed list without setting a variable as a side-effect\&. .TP \fBtsv::keylkeys\fR \fIvarname\fR \fIkeylist\fR ?key? Return the a list of the keys in the keyed list \fIkeylist\fR in the shared variable \fIvarname\fR\&. If \fIkey\fR is specified, then it is the name of a key field who's subfield keys are to be retrieved\&. .TP \fBtsv::keylset\fR \fIvarname\fR \fIkeylist\fR \fIkey\fR \fIvalue\fR ?key value\&.\&.? Set the value associated with \fIkey\fR, in the keyed list \fIkeylist\fR to \fIvalue\fR\&. If the \fIkeylist\fR does not exists, it is created\&. If \fIkey\fR is not currently in the list, it will be added\&. If it already exists, \fIvalue\fR replaces the existing value\&. Multiple keywords and values may be specified, if desired\&. .PP .SH DISCUSSION The current implementation of thread shared variables allows for easy and convenient access to data shared between different threads\&. Internally, the data is stored in Tcl objects and all package commands operate on internal data representation, thus minimizing shimmering and improving performance\&. Special care has been taken to assure that all object data is properly locked and deep-copied when moving objects between threads\&. .PP Due to the internal design of the Tcl core, there is no provision of full integration of shared variables within the Tcl syntax, unfortunately\&. All access to shared data must be performed with the supplied package commands\&. Also, variable traces are not supported\&. But even so, benefits of easy, simple and safe shared data manipulation outweights imposed limitations\&. .SH CREDITS Thread shared variables are inspired by the nsv interface found in AOLserver, a highly scalable Web server from America Online\&. .SH "SEE ALSO" thread, tpool, ttrace .SH KEYWORDS locking, synchronization, thread shared data, threads |
Changes to doc/man/ttrace.n.
1 2 3 | '\" '\" Generated from file '' by tcllib/doctools with format 'nroff' '\" | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > > > > > | < < < < < < < | | | | | | | | > > > > > > > > > | < < < < < < < < | | | | | | | | | > > > > > > > | | | | | | | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | '\" '\" Generated from file '' by tcllib/doctools with format 'nroff' '\" .TH "ttrace" n 2\&.8 "Tcl Threading" .\" The -*- nroff -*- definitions below are for supplemental macros used .\" in Tcl/Tk manual entries. .\" .\" .AP type name in/out ?indent? .\" Start paragraph describing an argument to a library procedure. .\" type is type of argument (int, etc.), in/out is either "in", "out", .\" or "in/out" to describe whether procedure reads or modifies arg, .\" and indent is equivalent to second arg of .IP (shouldn't ever be .\" needed; use .AS below instead) .\" .\" .AS ?type? ?name? .\" Give maximum sizes of arguments for setting tab stops. Type and .\" name are examples of largest possible arguments that will be passed .\" to .AP later. If args are omitted, default tab stops are used. .\" .\" .BS .\" Start box enclosure. From here until next .BE, everything will be .\" enclosed in one large box. .\" .\" .BE .\" End of box enclosure. .\" .\" .CS .\" Begin code excerpt. .\" .\" .CE .\" End code excerpt. .\" .\" .VS ?version? ?br? .\" Begin vertical sidebar, for use in marking newly-changed parts .\" of man pages. The first argument is ignored and used for recording .\" the version when the .VS was added, so that the sidebars can be .\" found and removed when they reach a certain age. If another argument .\" is present, then a line break is forced before starting the sidebar. .\" .\" .VE .\" End of vertical sidebar. .\" .\" .DS .\" Begin an indented unfilled display. .\" .\" .DE .\" End of indented unfilled display. .\" .\" .SO ?manpage? .\" Start of list of standard options for a Tk widget. The manpage .\" argument defines where to look up the standard options; if .\" omitted, defaults to "options". The options follow on successive .\" lines, in three columns separated by tabs. .\" .\" .SE .\" End of list of standard options for a Tk widget. .\" .\" .OP cmdName dbName dbClass .\" Start of description of a specific option. cmdName gives the .\" option's name as specified in the class command, dbName gives .\" the option's name in the option database, and dbClass gives .\" the option's class in the option database. .\" .\" .UL arg1 arg2 .\" Print arg1 underlined, then print arg2 normally. .\" .\" .QW arg1 ?arg2? .\" Print arg1 in quotes, then arg2 normally (for trailing punctuation). .\" .\" .PQ arg1 ?arg2? .\" Print an open parenthesis, arg1 in quotes, then arg2 normally .\" (for trailing punctuation) and then a closing parenthesis. .\" .\" # Set up traps and other miscellaneous stuff for Tcl/Tk man pages. .if t .wh -1.3i ^B .nr ^l \n(.l .ad b .\" # Start an argument description .de AP .ie !"\\$4"" .TP \\$4 .el \{\ . ie !"\\$2"" .TP \\n()Cu . el .TP 15 .\} .ta \\n()Au \\n()Bu .ie !"\\$3"" \{\ \&\\$1 \\fI\\$2\\fP (\\$3) .\".b .\} .el \{\ .br .ie !"\\$2"" \{\ \&\\$1 \\fI\\$2\\fP .\} .el \{\ \&\\fI\\$1\\fP .\} .\} .. .\" # define tabbing values for .AP .de AS .nr )A 10n .if !"\\$1"" .nr )A \\w'\\$1'u+3n .nr )B \\n()Au+15n .\" .if !"\\$2"" .nr )B \\w'\\$2'u+\\n()Au+3n .nr )C \\n()Bu+\\w'(in/out)'u+2n .. .AS Tcl_Interp Tcl_CreateInterp in/out .\" # BS - start boxed text .\" # ^y = starting y location .\" # ^b = 1 .de BS .br .mk ^y .nr ^b 1u .if n .nf .if n .ti 0 .if n \l'\\n(.lu\(ul' .if n .fi .. .\" # BE - end boxed text (draw box now) .de BE .nf .ti 0 .mk ^t .ie n \l'\\n(^lu\(ul' .el \{\ .\" Draw four-sided box normally, but don't draw top of .\" box if the box started on an earlier page. .ie !\\n(^b-1 \{\ \h'-1.5n'\L'|\\n(^yu-1v'\l'\\n(^lu+3n\(ul'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .el \}\ \h'-1.5n'\L'|\\n(^yu-1v'\h'\\n(^lu+3n'\L'\\n(^tu+1v-\\n(^yu'\l'|0u-1.5n\(ul' .\} .\} .fi .br .nr ^b 0 .. .\" # VS - start vertical sidebar .\" # ^Y = starting y location .\" # ^v = 1 (for troff; for nroff this doesn't matter) .de VS .if !"\\$2"" .br .mk ^Y .ie n 'mc \s12\(br\s0 .el .nr ^v 1u .. .\" # VE - end of vertical sidebar .de VE .ie n 'mc .el \{\ .ev 2 .nf .ti 0 .mk ^t \h'|\\n(^lu+3n'\L'|\\n(^Yu-1v\(bv'\v'\\n(^tu+1v-\\n(^Yu'\h'-|\\n(^lu+3n' .sp -1 .fi .ev .\} .nr ^v 0 .. .\" # Special macro to handle page bottom: finish off current .\" # box/sidebar if in box/sidebar mode, then invoked standard .\" # page bottom macro. .de ^B .ev 2 'ti 0 'nf .mk ^t .if \\n(^b \{\ .\" Draw three-sided box if this is the box's first page, |
︙ | ︙ | |||
180 181 182 183 184 185 186 | .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. | | | | > > | | | | < | < > | > > > > > > > > > > > > > > > > > > > | > | | | | | | 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | .mk ^y .nr ^b 2 .\} .if \\n(^v \{\ .mk ^Y .\} .. .\" # DS - begin display .de DS .RS .nf .sp .. .\" # DE - end display .de DE .fi .RE .sp .. .\" # SO - start of list of standard options .de SO 'ie '\\$1'' .ds So \\fBoptions\\fR 'el .ds So \\fB\\$1\\fR .SH "STANDARD OPTIONS" .LP .nf .ta 5.5c 11c .ft B .. .\" # SE - end of list of standard options .de SE .fi .ft R .LP See the \\*(So manual entry for details on the standard options. .. .\" # OP - start of full description for a single option .de OP .LP .nf .ta 4c Command-Line Name: \\fB\\$1\\fR Database Name: \\fB\\$2\\fR Database Class: \\fB\\$3\\fR .fi .IP .. .\" # CS - begin code excerpt .de CS .RS .nf .ta .25i .5i .75i 1i .. .\" # CE - end code excerpt .de CE .fi .RE .. .\" # UL - underline word .de UL \\$1\l'|0\(ul'\\$2 .. .\" # QW - apply quotation marks to word .de QW .ie '\\*(lq'"' ``\\$1''\\$2 .\"" fix emacs highlighting .el \\*(lq\\$1\\*(rq\\$2 .. .\" # PQ - apply parens and quotation marks to word .de PQ .ie '\\*(lq'"' (``\\$1''\\$2)\\$3 .\"" fix emacs highlighting .el (\\*(lq\\$1\\*(rq\\$2)\\$3 .. .\" # QR - quoted range .de QR .ie '\\*(lq'"' ``\\$1''\\-``\\$2''\\$3 .\"" fix emacs highlighting .el \\*(lq\\$1\\*(rq\\-\\*(lq\\$2\\*(rq\\$3 .. .\" # MT - "empty" string .de MT .QW "" .. .BS .SH NAME ttrace \- Trace-based interpreter initialization .SH SYNOPSIS package require \fBTcl 8\&.4\fR .sp package require \fBThread ?2\&.8?\fR .sp \fBttrace::eval\fR \fIarg\fR ?arg \&.\&.\&.? .sp \fBttrace::enable\fR .sp \fBttrace::disable\fR .sp \fBttrace::cleanup\fR .sp |
︙ | ︙ | |||
279 280 281 282 283 284 285 | \fBttrace::getentries\fR \fIcmd\fR ?pattern? .sp \fBttrace::delentry\fR \fIcmd\fR .sp \fBttrace::preload\fR \fIcmd\fR .sp .BE | | | | | | > > | | > | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > | | | | | | | | | | | | | 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 | \fBttrace::getentries\fR \fIcmd\fR ?pattern? .sp \fBttrace::delentry\fR \fIcmd\fR .sp \fBttrace::preload\fR \fIcmd\fR .sp .BE .SH DESCRIPTION This package creates a framework for on-demand replication of the interpreter state accross threads in an multithreading application\&. It relies on the mechanics of Tcl command tracing and the Tcl \fBunknown\fR command and mechanism\&. .PP The package requires Tcl threading extension but can be alternatively used stand-alone within the AOLserver, a scalable webserver from America Online\&. .PP In a nutshell, a short sample illustrating the usage of the ttrace with the Tcl threading extension: .CS % package require Ttrace 2\&.8\&.0 % set t1 [thread::create {package require Ttrace; thread::wait}] tid0x1802800 % ttrace::eval {proc test args {return test-[thread::id]}} % thread::send $t1 test test-tid0x1802800 % set t2 [thread::create {package require Ttrace; thread::wait}] tid0x1804000 % thread::send $t2 test test-tid0x1804000 .CE .PP As seen from above, the \fBttrace::eval\fR and \fBttrace::update\fR commands are used to create a thread-wide definition of a simple Tcl procedure and replicate that definition to all, already existing or later created, threads\&. .SH "USER COMMANDS" This section describes user-level commands\&. Those commands can be used by script writers to control the execution of the tracing framework\&. .TP \fBttrace::eval\fR \fIarg\fR ?arg \&.\&.\&.? This command concatenates given arguments and evaluates the resulting Tcl command with trace framework enabled\&. If the command execution was ok, it takes necessary steps to automatically propagate the trace epoch change to all threads in the application\&. For AOLserver, only newly created threads actually receive the epoch change\&. For the Tcl threading extension, all threads created by the extension are automatically updated\&. If the command execution resulted in Tcl error, no state propagation takes place\&. .sp This is the most important user-level command of the package as it wraps most of the commands described below\&. This greatly simplifies things, because user need to learn just this (one) command in order to effectively use the package\&. Other commands, as desribed below, are included mostly for the sake of completeness\&. .TP \fBttrace::enable\fR Activates all registered callbacks in the framework and starts a new trace epoch\&. The trace epoch encapsulates all changes done to the interpreter during the time traces are activated\&. .TP \fBttrace::disable\fR Deactivates all registered callbacks in the framework and closes the current trace epoch\&. .TP \fBttrace::cleanup\fR Used to clean-up all on-demand loaded resources in the interpreter\&. It effectively brings Tcl interpreter to its pristine state\&. .TP \fBttrace::update\fR ?epoch? Used to refresh the state of the interpreter to match the optional trace ?epoch?\&. If the optional ?epoch? is not given, it takes the most recent trace epoch\&. .TP \fBttrace::getscript\fR Returns a synthetized Tcl script which may be sourced in any interpreter\&. This script sets the stage for the Tcl \fBunknown\fR command so it can load traced resources from the in-memory database\&. Normally, this command is automatically invoked by other higher-level commands like \fBttrace::eval\fR and \fBttrace::update\fR\&. .PP .SH "CALLBACK COMMANDS" A word upfront: the package already includes callbacks for tracing following Tcl commands: \fBproc\fR, \fBnamespace\fR, \fBvariable\fR, \fBload\fR, and \fBrename\fR\&. Additionaly, a set of callbacks for tracing resources (object, clasess) for the XOTcl v1\&.3\&.8+, an OO-extension to Tcl, is also provided\&. This gives a solid base for solving most of the real-life needs and serves as an example for people wanting to customize the package to cover their specific needs\&. .PP Below, you can find commands for registering callbacks in the framework and for writing callback scripts\&. These callbacks are invoked by the framework in order to gather interpreter state changes, build in-memory database, perform custom-cleanups and various other tasks\&. .TP \fBttrace::atenable\fR \fIcmd\fR \fIarglist\fR \fIbody\fR Registers Tcl callback to be activated at \fBttrace::enable\fR\&. Registered callbacks are activated on FIFO basis\&. The callback definition includes the name of the callback, \fIcmd\fR, a list of callback arguments, \fIarglist\fR and the \fIbody\fR of the callback\&. Effectively, this actually resembles the call interface of the standard Tcl \fBproc\fR command\&. .TP \fBttrace::atdisable\fR \fIcmd\fR \fIarglist\fR \fIbody\fR Registers Tcl callback to be activated at \fBttrace::disable\fR\&. Registered callbacks are activated on FIFO basis\&. The callback definition includes the name of the callback, \fIcmd\fR, a list of callback arguments, \fIarglist\fR and the \fIbody\fR of the callback\&. Effectively, this actually resembles the call interface of the standard Tcl \fBproc\fR command\&. .TP \fBttrace::addtrace\fR \fIcmd\fR \fIarglist\fR \fIbody\fR Registers Tcl callback to be activated for tracing the Tcl \fBcmd\fR command\&. The callback definition includes the name of the Tcl command to trace, \fIcmd\fR, a list of callback arguments, \fIarglist\fR and the \fIbody\fR of the callback\&. Effectively, this actually resembles the call interface of the standard Tcl \fBproc\fR command\&. .TP \fBttrace::addscript\fR \fIname\fR \fIbody\fR Registers Tcl callback to be activated for building a Tcl script to be passed to other interpreters\&. This script is used to set the stage for the Tcl \fBunknown\fR command\&. Registered callbacks are activated on FIFO basis\&. The callback definition includes the name of the callback, \fIname\fR and the \fIbody\fR of the callback\&. .TP \fBttrace::addresolver\fR \fIcmd\fR \fIarglist\fR \fIbody\fR Registers Tcl callback to be activated by the overloaded Tcl \fBunknown\fR command\&. Registered callbacks are activated on FIFO basis\&. This callback is used to resolve the resource and load the resource in the current interpreter\&. .TP \fBttrace::addcleanup\fR \fIbody\fR Registers Tcl callback to be activated by the \fBtrace::cleanup\fR\&. Registered callbacks are activated on FIFO basis\&. .TP \fBttrace::addentry\fR \fIcmd\fR \fIvar\fR \fIval\fR Adds one entry to the named in-memory database\&. .TP \fBttrace::getentry\fR \fIcmd\fR \fIvar\fR Returns the value of the entry from the named in-memory database\&. .TP \fBttrace::getentries\fR \fIcmd\fR ?pattern? Returns names of all entries from the named in-memory database\&. .TP \fBttrace::delentry\fR \fIcmd\fR Deletes an entry from the named in-memory database\&. .TP \fBttrace::preload\fR \fIcmd\fR Registers the Tcl command to be loaded in the interpreter\&. Commands registered this way will always be the part of the interpreter and not be on-demand loaded by the Tcl \fBunknown\fR command\&. .PP .SH DISCUSSION Common introspective state-replication approaches use a custom Tcl script to introspect the running interpreter and synthesize another Tcl script to replicate this state in some other interpreter\&. This package, on the contrary, uses Tcl command traces\&. Command traces are registered on selected Tcl commands, like \fBproc\fR, \fBnamespace\fR, \fBload\fR and other standard (and/or user-defined) Tcl commands\&. When activated, those traces build an in-memory database of created resources\&. This database is used as a resource repository for the (overloaded) Tcl \fBunknown\fR command which creates the requested resource in the interpreter on demand\&. This way, users can update just one interpreter (master) in one thread and replicate that interpreter state (or part of it) to other threads/interpreters in the process\&. .PP Immediate benefit of such approach is the much smaller memory footprint of the application and much faster thread creation\&. By not actually loading all necessary procedures (and other resources) in every thread at the thread initialization time, but by deffering this to the time the resource is actually referenced, significant improvements in both memory consumption and thread initialization time can be achieved\&. Some tests have shown that memory footprint of an multithreading Tcl application went down more than three times and thread startup time was reduced for about 50 times\&. Note that your mileage may vary\&. Other benefits include much finer control about what (and when) gets replicated from the master to other Tcl thread/interpreters\&. .SH "SEE ALSO" thread, tpool, tsv .SH KEYWORDS command tracing, introspection |
Changes to doc/thread.man.
1 | [comment {-*- tcl -*- doctools manpage}] | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 | [comment {-*- tcl -*- doctools manpage}] [manpage_begin thread n 2.8] [moddesc {Tcl Threading}] [titledesc {Extension for script access to Tcl threading}] [require Tcl 8.4] [require Thread [opt 2.8]] [description] The [package thread] extension creates threads that contain Tcl interpreters, and it lets you send scripts to those threads for evaluation. Additionaly, it provides script-level access to basic thread |
︙ | ︙ | |||
195 196 197 198 199 200 201 | the script passed to newly created thread will continue from the [cmd thread::wait] command. If [cmd thread::wait] was the last command in the script, the thread will exit. The command returns empty result but may trigger Tcl error with the message "target thread died" in some situations. | | | | > | | | | | | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | the script passed to newly created thread will continue from the [cmd thread::wait] command. If [cmd thread::wait] was the last command in the script, the thread will exit. The command returns empty result but may trigger Tcl error with the message "target thread died" in some situations. [call [cmd thread::exit] [opt status]] Use of this command is deprecated in favour of more advanced thread reservation system implemented with [cmd thread::preserve] and [cmd thread::release] commands. Support for [cmd thread::exit] command will dissapear in some future major release of the extension. [para] This command forces a thread stuck in the [cmd thread::wait] command to unconditionaly exit. The thread's exit status defaults to 666 and can be specified using the optional [arg status] argument. The execution of [cmd thread::exit] command is guaranteed to leave the program memory in the unconsistent state, produce memory leaks and otherwise affect other subsytem(s) of the Tcl application in an unpredictable manner. The command returns empty result but may trigger Tcl error with the message "target thread died" in some situations. [call [cmd thread::names]] This command returns a list of thread IDs. These are only for threads that have been created via [cmd thread::create] command. If your application creates other threads at the C level, they are not reported by this command. |
︙ | ︙ | |||
272 273 274 275 276 277 278 | thread and executed on the FIFO basis, intermingled with optional other events pending in the event queue of the target thread. Using the optional [opt -head] switch, scripts posted to the thread's event queue can be placed on the head, instead on the tail of the queue, thus being executed in the LIFO fashion. | | | 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | thread and executed on the FIFO basis, intermingled with optional other events pending in the event queue of the target thread. Using the optional [opt -head] switch, scripts posted to the thread's event queue can be placed on the head, instead on the tail of the queue, thus being executed in the LIFO fashion. [call [cmd thread::broadcast] [arg script]] This command passes a [arg script] to all threads created by the package for execution. It does not wait for response from any of the threads. [call [cmd thread::wait]] |
︙ | ︙ |
Changes to doc/tpool.man.
1 | [comment {-*- tcl -*- doctools manpage}] | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 | [comment {-*- tcl -*- doctools manpage}] [manpage_begin tpool n 2.8] [moddesc {Tcl Threading}] [titledesc {Part of the Tcl threading extension implementing pools of worker threads.}] [require Tcl 8.4] [require Thread [opt 2.8]] [description] This package creates and manages pools of worker threads. It allows you to post jobs to worker threads and wait for their completion. The threadpool implementation is Tcl event-loop aware. That means that any time a caller is forced to wait for an event (job being completed or a worker thread becoming idle or initialized), the implementation will |
︙ | ︙ |
Changes to doc/tsv.man.
1 | [comment {-*- tcl -*- doctools manpage}] | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 | [comment {-*- tcl -*- doctools manpage}] [manpage_begin tsv n 2.8] [moddesc {Tcl Threading}] [titledesc {Part of the Tcl threading extension allowing script level manipulation of data shared between threads.}] [require Tcl 8.4] [require Thread [opt 2.8]] [description] This section describes commands implementing thread shared variables. A thread shared variable is very similar to a Tcl array but in contrast to a Tcl array it is created in shared memory and can be accessed from many threads at the same time. Important feature of thread shared variable is that each access to the variable is internaly |
︙ | ︙ | |||
110 111 112 113 114 115 116 117 118 119 120 121 122 123 | tsv::lappend foo bar 1 tsv::lappend foo bar 2 puts stderr [tsv::set foo bar] tsv::unset foo } }] [list_end] [section {LIST COMMANDS}] Those command are similar to the equivalently named Tcl command. The difference is that they operate on elements of shared arrays. | > > > > > | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | tsv::lappend foo bar 1 tsv::lappend foo bar 2 puts stderr [tsv::set foo bar] tsv::unset foo } }] [call [cmd tsv::handlers]] Returns the names of all persistent storage handlers enabled at compile time. See [sectref {ARRAY COMMANDS}] for details. [list_end] [section {LIST COMMANDS}] Those command are similar to the equivalently named Tcl command. The difference is that they operate on elements of shared arrays. |
︙ | ︙ | |||
185 186 187 188 189 190 191 | [list_end] [section {ARRAY COMMANDS}] This command supports most of the options of the standard Tcl [cmd array] command. In addition to those, it allows binding | | | | | | | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | [list_end] [section {ARRAY COMMANDS}] This command supports most of the options of the standard Tcl [cmd array] command. In addition to those, it allows binding a shared variable to some persisten storage databases. Currently the persistent options supported are the famous GNU Gdbm and LMDB. These options have to be selected during the package compilation time. The implementation provides hooks for defining other persistency layers, if needed. [list_begin definitions] [call [cmd {tsv::array set}] [arg varname] [arg list]] Does the same as standard Tcl [cmd {array set}]. |
︙ | ︙ | |||
216 217 218 219 220 221 222 | [call [cmd {tsv::array reset}] [arg varname] [arg list]] Does the same as standard Tcl [cmd {array set}] but it clears the [arg varname] and sets new values from the list atomically. [call [cmd {tsv::array bind}] [arg varname] [arg handle]] Binds the [arg varname] to the persistent storage [arg handle]. | | | | | 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | [call [cmd {tsv::array reset}] [arg varname] [arg list]] Does the same as standard Tcl [cmd {array set}] but it clears the [arg varname] and sets new values from the list atomically. [call [cmd {tsv::array bind}] [arg varname] [arg handle]] Binds the [arg varname] to the persistent storage [arg handle]. The format of the [arg handle] is <handler>:<address>, where <handler> is "gdbm" for GNU Gdbm and "lmdb" for LMDB and <address> is the path to the database file. [call [cmd {tsv::array unbind}] [arg varname]] Unbinds the shared [arg array] from its bound persistent storage. [call [cmd {tsv::array isbound}] [arg varname]] Returns true (1) if the shared [arg varname] is bound to some persistent storage or zero (0) if not. |
︙ | ︙ |
Changes to doc/ttrace.man.
1 | [comment {-*- tcl -*- doctools manpage}] | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | [comment {-*- tcl -*- doctools manpage}] [manpage_begin ttrace n 2.8] [moddesc {Tcl Threading}] [titledesc {Trace-based interpreter initialization}] [require Tcl 8.4] [require Thread [opt 2.8]] [description] This package creates a framework for on-demand replication of the interpreter state accross threads in an multithreading application. It relies on the mechanics of Tcl command tracing and the Tcl [cmd unknown] command and mechanism. [para] The package requires Tcl threading extension but can be alternatively used stand-alone within the AOLserver, a scalable webserver from America Online. [para] In a nutshell, a short sample illustrating the usage of the ttrace with the Tcl threading extension: [example { % package require Ttrace 2.8.0 % set t1 [thread::create {package require Ttrace; thread::wait}] tid0x1802800 % ttrace::eval {proc test args {return test-[thread::id]}} % thread::send $t1 test test-tid0x1802800 |
︙ | ︙ |
Changes to generic/psGdbm.c.
︙ | ︙ | |||
343 344 345 346 347 348 349 | * Side effects: * Memory gets reclaimed. * *----------------------------------------------------------------------------- */ static void ps_gdbm_free( | > | > | 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 | * Side effects: * Memory gets reclaimed. * *----------------------------------------------------------------------------- */ static void ps_gdbm_free( ClientData handle, void *data) { (void)handle; free(data); } /* *----------------------------------------------------------------------------- * * ps_gdbm_geterr -- |
︙ | ︙ |
Added generic/psLmdb.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 | /* * This file implements wrappers for persistent lmdb storage for the * shared variable arrays. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * ---------------------------------------------------------------------------- */ #ifdef HAVE_LMDB #include "threadSvCmd.h" #include <lmdb.h> /* * Structure keeping the lmdb environment context */ typedef struct { MDB_env * env; // Environment MDB_txn * txn; // Last active read transaction MDB_cursor * cur; // Cursor used for ps_lmdb_first and ps_lmdb_next MDB_dbi dbi; // Open database (default db) int err; // Last error (used in ps_lmdb_geterr) } * LmdbCtx; /* * Transaction and DB open mode */ enum LmdbOpenMode { LmdbRead, LmdbWrite }; // Initialize or renew a transaction. static void LmdbTxnGet(LmdbCtx ctx, enum LmdbOpenMode mode); // Commit a transaction. static void LmdbTxnCommit(LmdbCtx ctx); // Abort a transaction static void LmdbTxnAbort(LmdbCtx ctx); void LmdbTxnGet(LmdbCtx ctx, enum LmdbOpenMode mode) { // Read transactions are reused, if possible if (ctx->txn && mode == LmdbRead) { ctx->err = mdb_txn_renew(ctx->txn); if (ctx->err) { ctx->txn = NULL; } } else if (ctx->txn && mode == LmdbWrite) { LmdbTxnAbort(ctx); } if (ctx->txn == NULL) { ctx->err = mdb_txn_begin(ctx->env, NULL, 0, &ctx->txn); } if (ctx->err) { ctx->txn = NULL; return; } // Given the setup above, and the arguments given, this won't fail. mdb_dbi_open(ctx->txn, NULL, 0, &ctx->dbi); } void LmdbTxnCommit(LmdbCtx ctx) { ctx->err = mdb_txn_commit(ctx->txn); ctx->txn = NULL; } void LmdbTxnAbort(LmdbCtx ctx) { mdb_txn_abort(ctx->txn); ctx->txn = NULL; } /* * Functions implementing the persistent store interface */ static ps_open_proc ps_lmdb_open; static ps_close_proc ps_lmdb_close; static ps_get_proc ps_lmdb_get; static ps_put_proc ps_lmdb_put; static ps_first_proc ps_lmdb_first; static ps_next_proc ps_lmdb_next; static ps_delete_proc ps_lmdb_delete; static ps_free_proc ps_lmdb_free; static ps_geterr_proc ps_lmdb_geterr; /* * This structure collects all the various pointers * to the functions implementing the lmdb store. */ const PsStore LmdbStore = { "lmdb", NULL, ps_lmdb_open, ps_lmdb_get, ps_lmdb_put, ps_lmdb_first, ps_lmdb_next, ps_lmdb_delete, ps_lmdb_close, ps_lmdb_free, ps_lmdb_geterr, NULL }; /* *----------------------------------------------------------------------------- * * Sv_RegisterLmdbStore -- * * Register the lmdb store with shared variable implementation. * * Results: * None. * * Side effects: * None. * *----------------------------------------------------------------------------- */ void Sv_RegisterLmdbStore(void) { Sv_RegisterPsStore(&LmdbStore); } /* *----------------------------------------------------------------------------- * * ps_lmdb_open -- * * Opens the lmdb-based persistent storage. * * Results: * Opaque handle for LmdbCtx. * * Side effects: * The lmdb file might be created if not found. * *----------------------------------------------------------------------------- */ static ClientData ps_lmdb_open( const char *path) { LmdbCtx ctx; char *ext; Tcl_DString toext; ctx = ckalloc(sizeof(*ctx)); if (ctx == NULL) { return NULL; } ctx->env = NULL; ctx->txn = NULL; ctx->cur = NULL; ctx->dbi = 0; ctx->err = mdb_env_create(&ctx->env); if (ctx->err) { ckfree(ctx); return NULL; } Tcl_DStringInit(&toext); ext = Tcl_UtfToExternalDString(NULL, path, strlen(path), &toext); ctx->err = mdb_env_open(ctx->env, ext, MDB_NOSUBDIR|MDB_NOLOCK, 0666); Tcl_DStringFree(&toext); if (ctx->err) { ckfree(ctx); return NULL; } return (ClientData)ctx; } /* *----------------------------------------------------------------------------- * * ps_lmdb_close -- * * Closes the lmdb-based persistent storage. * * Results: * 0 - ok * * Side effects: * None. * *----------------------------------------------------------------------------- */ static int ps_lmdb_close( ClientData handle) { LmdbCtx ctx = (LmdbCtx)handle; if (ctx->cur) { mdb_cursor_close(ctx->cur); } if (ctx->txn) { LmdbTxnAbort(ctx); } mdb_env_close(ctx->env); ckfree(ctx); return 0; } /* *----------------------------------------------------------------------------- * * ps_lmdb_get -- * * Retrieves data for the key from the lmdb storage. * * Results: * 1 - no such key * 0 - ok * * Side effects: * Data returned must be copied, then psFree must be called. * *----------------------------------------------------------------------------- */ static int ps_lmdb_get( ClientData handle, const char *keyptr, char **dataptrptr, size_t *lenptr) { LmdbCtx ctx = (LmdbCtx)handle; MDB_val key, data; LmdbTxnGet(ctx, LmdbRead); if (ctx->err) { return 1; } key.mv_data = (void *)keyptr; key.mv_size = strlen(keyptr) + 1; ctx->err = mdb_get(ctx->txn, ctx->dbi, &key, &data); if (ctx->err) { mdb_txn_reset(ctx->txn); return 1; } *dataptrptr = data.mv_data; *lenptr = data.mv_size; /* * Transaction is left open at this point, so that the caller can get ahold * of the data and make a copy of it. Afterwards, it will call ps_lmdb_free * to free the data, and we'll catch the chance to reset the transaction * there. */ return 0; } /* *----------------------------------------------------------------------------- * * ps_lmdb_first -- * * Starts the iterator over the lmdb file and returns the first record. * * Results: * 1 - no more records in the iterator * 0 - ok * * Side effects: * Data returned must be copied, then psFree must be called. * *----------------------------------------------------------------------------- */ static int ps_lmdb_first( ClientData handle, char **keyptrptr, char **dataptrptr, size_t *lenptr) { LmdbCtx ctx = (LmdbCtx)handle; MDB_val key, data; LmdbTxnGet(ctx, LmdbRead); if (ctx->err) { return 1; } ctx->err = mdb_cursor_open(ctx->txn, ctx->dbi, &ctx->cur); if (ctx->err) { return 1; } ctx->err = mdb_cursor_get(ctx->cur, &key, &data, MDB_FIRST); if (ctx->err) { mdb_txn_reset(ctx->txn); mdb_cursor_close(ctx->cur); ctx->cur = NULL; return 1; } *dataptrptr = data.mv_data; *lenptr = data.mv_size; *keyptrptr = key.mv_data; return 0; } /* *----------------------------------------------------------------------------- * * ps_lmdb_next -- * * Uses the iterator over the lmdb file and returns the next record. * * Results: * 1 - no more records in the iterator * 0 - ok * * Side effects: * Data returned must be copied, then psFree must be called. * *----------------------------------------------------------------------------- */ static int ps_lmdb_next( ClientData handle, char **keyptrptr, char **dataptrptr, size_t *lenptr) { LmdbCtx ctx = (LmdbCtx)handle; MDB_val key, data; ctx->err = mdb_cursor_get(ctx->cur, &key, &data, MDB_NEXT); if (ctx->err) { mdb_txn_reset(ctx->txn); mdb_cursor_close(ctx->cur); ctx->cur = NULL; return 1; } *dataptrptr = data.mv_data; *lenptr = data.mv_size; *keyptrptr = key.mv_data; return 0; } /* *----------------------------------------------------------------------------- * * ps_lmdb_put -- * * Stores used data bound to a key in lmdb storage. * * Results: * 0 - ok * -1 - error; use ps_lmdb_geterr to retrieve the error message * * Side effects: * If the key is already associated with some user data, this will * be replaced by the new data chunk. * *----------------------------------------------------------------------------- */ static int ps_lmdb_put( ClientData handle, const char *keyptr, char *dataptr, size_t len) { LmdbCtx ctx = (LmdbCtx)handle; MDB_val key, data; LmdbTxnGet(ctx, LmdbWrite); if (ctx->err) { return -1; } key.mv_data = (void*)keyptr; key.mv_size = strlen(keyptr) + 1; data.mv_data = dataptr; data.mv_size = len; ctx->err = mdb_put(ctx->txn, ctx->dbi, &key, &data, 0); if (ctx->err) { LmdbTxnAbort(ctx); } else { LmdbTxnCommit(ctx); } return ctx->err ? -1 : 0; } /* *----------------------------------------------------------------------------- * * ps_lmdb_delete -- * * Deletes the key and associated data from the lmdb storage. * * Results: * 0 - ok * -1 - error; use ps_lmdb_geterr to retrieve the error message * * Side effects: * If the key is already associated with some user data, this will * be replaced by the new data chunk. * *----------------------------------------------------------------------------- */ static int ps_lmdb_delete( ClientData handle, const char *keyptr) { LmdbCtx ctx = (LmdbCtx)handle; MDB_val key; LmdbTxnGet(ctx, LmdbWrite); if (ctx->err) { return -1; } key.mv_data = (void*)keyptr; key.mv_size = strlen(keyptr) + 1; ctx->err = mdb_del(ctx->txn, ctx->dbi, &key, NULL); if (ctx->err) { LmdbTxnAbort(ctx); } else { LmdbTxnCommit(ctx); } ctx->txn = NULL; return ctx->err ? -1 : 0; } /* *----------------------------------------------------------------------------- * * ps_lmdb_free -- * * This function is called to free data returned by the persistent store * after calls to psFirst, psNext, or psGet. Lmdb doesn't need to free any * data, as the data returned is owned by lmdb. On the other hand, this * method is required to reset the read transaction. This is done only * when iteration is over (ctx->cur == NULL). * * Results: * None. * * Side effects: * Memory gets reclaimed. * *----------------------------------------------------------------------------- */ static void ps_lmdb_free( ClientData handle, void *data) { LmdbCtx ctx = (LmdbCtx)handle; (void)data; if (ctx->cur == NULL) { mdb_txn_reset(ctx->txn); } } /* *----------------------------------------------------------------------------- * * ps_lmdb_geterr -- * * Retrieves the textual representation of the error caused * by the last lmdb command. * * Results: * Pointer to the string message. * * Side effects: * None. * *----------------------------------------------------------------------------- */ static const char* ps_lmdb_geterr( ClientData handle) { LmdbCtx ctx = (LmdbCtx)handle; return mdb_strerror(ctx->err); } #endif /* HAVE_LMDB */ /* EOF $RCSfile*/ /* Emacs Setup Variables */ /* Local Variables: */ /* mode: C */ /* indent-tabs-mode: nil */ /* c-basic-offset: 4 */ /* End: */ |
Added generic/psLmdb.h.
> > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /* * psLmdb.h -- * * See the file "license.txt" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * --------------------------------------------------------------------------- */ #ifndef _PSLMDB_H_ #define _PSLMDB_H_ void Sv_RegisterLmdbStore(); #endif /* _PSLMDB_H_ */ /* EOF $RCSfile */ /* Emacs Setup Variables */ /* Local Variables: */ /* mode: C */ /* indent-tabs-mode: nil */ /* c-basic-offset: 4 */ /* End: */ |
Changes to generic/tclThreadInt.h.
︙ | ︙ | |||
22 23 24 25 26 27 28 | /* * Used to tag functions that are only to be visible within the module being * built and not outside it (where this is supported by the linker). */ #ifndef MODULE_SCOPE # ifdef __cplusplus | | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | /* * Used to tag functions that are only to be visible within the module being * built and not outside it (where this is supported by the linker). */ #ifndef MODULE_SCOPE # ifdef __cplusplus # define MODULE_SCOPE extern "C" # else # define MODULE_SCOPE extern # endif #endif /* * For linking against NaviServer/AOLserver require V4 at least */ |
︙ | ︙ |
Changes to generic/tclXkeylist.c.
︙ | ︙ | |||
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | *----------------------------------------------------------------------------- */ #include "tclThreadInt.h" #include "threadSvCmd.h" #include "tclXkeylist.h" #undef Tcl_RegisterObjType #define Tcl_RegisterObjType(typePtr) if (threadTclVersion<90) { \ ((void (*)(const Tcl_ObjType *))((&(tclStubsPtr->tcl_PkgProvideEx))[211]))(typePtr); \ } else { \ (typePtr)->setFromAnyProc = NULL; \ } /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stuff copied verbatim from the rest of TclX to avoid dependencies */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ | > > > > > > > > > > > > > > > > > > > > | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | *----------------------------------------------------------------------------- */ #include "tclThreadInt.h" #include "threadSvCmd.h" #include "tclXkeylist.h" #ifdef STATIC_BUILD #if TCL_MAJOR_VERSION >= 9 /* * Static build, Tcl >= 9, compile-time decision to disable T_ROT calls. */ #undef Tcl_RegisterObjType #define Tcl_RegisterObjType(typePtr) (typePtr)->setFromAnyProc = NULL #else /* * Static build, Tcl <= 9 --> T_ROT is directly linked, no stubs * Nothing needs to be done */ #endif #else /* !STATIC_BUILD */ /* * Dynamic build. Assume building with stubs (xx) and make a run-time * decision regarding T_ROT. * (Ad xx): Should be checked. Without stubs we have to go like static. */ #undef Tcl_RegisterObjType #define Tcl_RegisterObjType(typePtr) if (threadTclVersion<90) { \ ((void (*)(const Tcl_ObjType *))((&(tclStubsPtr->tcl_PkgProvideEx))[211]))(typePtr); \ } else { \ (typePtr)->setFromAnyProc = NULL; \ } #endif /* eof STATIC_BUILD */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ /* Stuff copied verbatim from the rest of TclX to avoid dependencies */ /*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/ |
︙ | ︙ | |||
89 90 91 92 93 94 95 | *----------------------------------------------------------------------------- */ static int TclX_IsNullObj (objPtr) Tcl_Obj *objPtr; { if (objPtr->typePtr == NULL) { | | | | | | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | *----------------------------------------------------------------------------- */ static int TclX_IsNullObj (objPtr) Tcl_Obj *objPtr; { if (objPtr->typePtr == NULL) { return (objPtr->length == 0); } else if (objPtr->typePtr == listType) { int length; Tcl_ListObjLength(NULL, objPtr, &length); return (length == 0); } (void)Tcl_GetString(objPtr); return (objPtr->length == 0); } /*----------------------------------------------------------------------------- * TclX_AppendObjResult -- |
︙ | ︙ | |||
869 870 871 872 873 874 875 | Tcl_Obj **valuePtrPtr; { keylIntObj_t *keylIntPtr; const char *nextSubKey; int findIdx; if (keylPtr->typePtr != &keyedListType) { | | | | | 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 | Tcl_Obj **valuePtrPtr; { keylIntObj_t *keylIntPtr; const char *nextSubKey; int findIdx; if (keylPtr->typePtr != &keyedListType) { if (SetKeyedListFromAny(interp, keylPtr) != TCL_OK) { return TCL_ERROR; } } keylIntPtr = keylPtr->internalRep.twoPtrValue.ptr1; KEYL_REP_ASSERT (keylIntPtr); findIdx = FindKeyedListEntry (keylIntPtr, key, NULL, &nextSubKey); /* |
︙ | ︙ | |||
928 929 930 931 932 933 934 | { keylIntObj_t *keylIntPtr; const char *nextSubKey; int findIdx, keyLen, status; Tcl_Obj *newKeylPtr; if (keylPtr->typePtr != &keyedListType) { | | | | | 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 | { keylIntObj_t *keylIntPtr; const char *nextSubKey; int findIdx, keyLen, status; Tcl_Obj *newKeylPtr; if (keylPtr->typePtr != &keyedListType) { if (SetKeyedListFromAny(interp, keylPtr) != TCL_OK) { return TCL_ERROR; } } keylIntPtr = keylPtr->internalRep.twoPtrValue.ptr1; KEYL_REP_ASSERT (keylIntPtr); findIdx = FindKeyedListEntry (keylIntPtr, key, &keyLen, &nextSubKey); |
︙ | ︙ | |||
1028 1029 1030 1031 1032 1033 1034 | const char *key; { keylIntObj_t *keylIntPtr, *subKeylIntPtr; const char *nextSubKey; int findIdx, status; if (keylPtr->typePtr != &keyedListType) { | | | | | 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 | const char *key; { keylIntObj_t *keylIntPtr, *subKeylIntPtr; const char *nextSubKey; int findIdx, status; if (keylPtr->typePtr != &keyedListType) { if (SetKeyedListFromAny(interp, keylPtr) != TCL_OK) { return TCL_ERROR; } } keylIntPtr = keylPtr->internalRep.twoPtrValue.ptr1; findIdx = FindKeyedListEntry (keylIntPtr, key, NULL, &nextSubKey); /* * If not found, return status. |
︙ | ︙ | |||
1107 1108 1109 1110 1111 1112 1113 | { keylIntObj_t *keylIntPtr; Tcl_Obj *nameObjPtr, *listObjPtr; const char *nextSubKey; int idx, findIdx; if (keylPtr->typePtr != &keyedListType) { | | | | | 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 | { keylIntObj_t *keylIntPtr; Tcl_Obj *nameObjPtr, *listObjPtr; const char *nextSubKey; int idx, findIdx; if (keylPtr->typePtr != &keyedListType) { if (SetKeyedListFromAny(interp, keylPtr) != TCL_OK) { return TCL_ERROR; } } keylIntPtr = keylPtr->internalRep.twoPtrValue.ptr1; /* * If key is not NULL or empty, then recurse down until we go past * the end of all of the elements of the key. */ |
︙ | ︙ |
Changes to generic/threadCmd.c.
︙ | ︙ | |||
17 18 19 20 21 22 23 24 | * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * ---------------------------------------------------------------------------- */ #include "tclThreadInt.h" #ifndef PACKAGE_VERSION | > > > > > | | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * ---------------------------------------------------------------------------- */ #include "tclThreadInt.h" /* * Provide package version in build contexts which do not provide * -DPACKAGE_VERSION, like building a shell with the Thread object * files built as part of that shell. Example: basekits. */ #ifndef PACKAGE_VERSION #define PACKAGE_VERSION "2.8.0" #endif /* * Check if this is Tcl 8.5 or higher. In that case, we will have the TIP * #143 APIs (i.e. interpreter resource limiting) available. */ |
︙ | ︙ | |||
68 69 70 71 72 73 74 | * If TIP #285 support is enabled and we are compiling against a pre-Tcl 8.6 * core, hard-wire the necessary APIs using the "well-known" offsets into the * stubs table. */ #if defined(TCL_TIP285) && !TCL_MINIMUM_VERSION(8,6) # if defined(USE_TCL_STUBS) | | | 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | * If TIP #285 support is enabled and we are compiling against a pre-Tcl 8.6 * core, hard-wire the necessary APIs using the "well-known" offsets into the * stubs table. */ #if defined(TCL_TIP285) && !TCL_MINIMUM_VERSION(8,6) # if defined(USE_TCL_STUBS) # define TCL_CANCEL_UNWIND 0x100000 # define Tcl_CancelEval ((int (*)(Tcl_Interp *, Tcl_Obj *, ClientData, int)) \ ((&(tclStubsPtr->tcl_PkgProvideEx))[580])) # define Tcl_Canceled ((int (*)(Tcl_Interp *, int)) \ ((&(tclStubsPtr->tcl_PkgProvideEx))[581])) # else # error "Supporting TIP #285 requires USE_TCL_STUBS before Tcl 8.6" # endif |
︙ | ︙ | |||
261 262 263 264 265 266 267 | static Tcl_ThreadId errorThreadId; /* Id of thread to post error message */ static char *errorProcString; /* Tcl script to run when reporting error */ /* * Definition of flags for ThreadSend. */ | | | > | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | static Tcl_ThreadId errorThreadId; /* Id of thread to post error message */ static char *errorProcString; /* Tcl script to run when reporting error */ /* * Definition of flags for ThreadSend. */ #define THREAD_SEND_WAIT (1<<1) #define THREAD_SEND_HEAD (1<<2) #define THREAD_SEND_CLBK (1<<3) #ifdef BUILD_thread # undef TCL_STORAGE_CLASS # define TCL_STORAGE_CLASS DLLEXPORT #endif /* |
︙ | ︙ | |||
425 426 427 428 429 430 431 | #endif static int ThreadInit(interp) Tcl_Interp *interp; /* The current Tcl interpreter */ { if (Tcl_InitStubs(interp, "8.4", 0) == NULL) { | | | | | | | | | | | | | | | | | | | | | | | | 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 | #endif static int ThreadInit(interp) Tcl_Interp *interp; /* The current Tcl interpreter */ { if (Tcl_InitStubs(interp, "8.4", 0) == NULL) { if ((sizeof(size_t) != sizeof(int)) || !Tcl_InitStubs(interp, "8.4-", 0)) { return TCL_ERROR; } Tcl_ResetResult(interp); } if (!threadTclVersion) { /* * Check whether we are running threaded Tcl. * Get the current core version to decide whether to use * some lately introduced core features or to back-off. */ int major, minor; Tcl_MutexLock(&threadMutex); if (threadMutex == NULL){ /* If threadMutex==NULL here, it means that Tcl_MutexLock() is * a dummy function, which is the case in unthreaded Tcl */ const char *msg = "Tcl core wasn't compiled for threading"; Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1)); return TCL_ERROR; } Tcl_GetVersion(&major, &minor, NULL, NULL); threadTclVersion = 10 * major + minor; Tcl_MutexUnlock(&threadMutex); } TCL_CMD(interp, THREAD_CMD_PREFIX"create", ThreadCreateObjCmd); TCL_CMD(interp, THREAD_CMD_PREFIX"send", ThreadSendObjCmd); TCL_CMD(interp, THREAD_CMD_PREFIX"broadcast", ThreadBroadcastObjCmd); TCL_CMD(interp, THREAD_CMD_PREFIX"exit", ThreadExitObjCmd); TCL_CMD(interp, THREAD_CMD_PREFIX"unwind", ThreadUnwindObjCmd); |
︙ | ︙ | |||
703 704 705 706 707 708 709 | if (objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "?-wait? ?threadId?"); return TCL_ERROR; } if (objc > 1) { if (OPT_CMP(Tcl_GetString(objv[1]), "-wait")) { wait = 1; | | | | | | | 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 | if (objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "?-wait? ?threadId?"); return TCL_ERROR; } if (objc > 1) { if (OPT_CMP(Tcl_GetString(objv[1]), "-wait")) { wait = 1; if (objc > 2) { if (ThreadGetId(interp, objv[2], &thrId) != TCL_OK) { return TCL_ERROR; } } } else if (ThreadGetId(interp, objv[1], &thrId) != TCL_OK) { return TCL_ERROR; } } return ThreadReserve(interp, thrId, THREAD_RELEASE, wait); } |
︙ | ︙ | |||
775 776 777 778 779 780 781 782 783 784 785 | static int ThreadExitObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *const objv[]; /* Argument objects. */ { Init(interp); ListRemove(NULL); | > > > > > > > > > > > > > | | 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 | static int ThreadExitObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *const objv[]; /* Argument objects. */ { int status = 666; Init(interp); if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?status?"); return TCL_ERROR; } if (objc == 2) { if (Tcl_GetIntFromObj(interp, objv[1], &status) != TCL_OK) { return TCL_ERROR; } } ListRemove(NULL); Tcl_ExitThread(status); return TCL_OK; /* NOT REACHED */ } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
905 906 907 908 909 910 911 | * *---------------------------------------------------------------------- */ static void threadSendFree(ClientData ptr) { | | | 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 | * *---------------------------------------------------------------------- */ static void threadSendFree(ClientData ptr) { ckfree((char *)ptr); } static int ThreadSendObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ |
︙ | ︙ | |||
1187 1188 1189 1190 1191 1192 1193 | } else { if (errorProcString) { ckfree(errorProcString); } proc = Tcl_GetString(objv[1]); len = objv[1]->length; if (len == 0) { | | | | | | | | 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 | } else { if (errorProcString) { ckfree(errorProcString); } proc = Tcl_GetString(objv[1]); len = objv[1]->length; if (len == 0) { errorThreadId = NULL; errorProcString = NULL; } else { errorThreadId = Tcl_GetCurrentThread(); errorProcString = ckalloc(1+strlen(proc)); strcpy(errorProcString, proc); Tcl_DeleteThreadExitHandler(ThreadFreeError, NULL); Tcl_CreateThreadExitHandler(ThreadFreeError, NULL); } } Tcl_MutexUnlock(&threadMutex); return TCL_OK; } static void ThreadFreeError(clientData) ClientData clientData; { Tcl_MutexLock(&threadMutex); if (errorThreadId != Tcl_GetCurrentThread()) { Tcl_MutexUnlock(&threadMutex); return; } ckfree(errorProcString); errorThreadId = NULL; errorProcString = NULL; Tcl_MutexUnlock(&threadMutex); } |
︙ | ︙ | |||
1448 1449 1450 1451 1452 1453 1454 | } /* *---------------------------------------------------------------------- * * ThreadConfigureObjCmd -- * | | | | | | 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 | } /* *---------------------------------------------------------------------- * * ThreadConfigureObjCmd -- * * This procedure is invoked to process the Tcl "thread::configure" * command. See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. *---------------------------------------------------------------------- */ static int ThreadConfigureObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *const objv[]; /* Argument objects. */ { char *option, *value; Tcl_ThreadId thrId; /* Id of the thread to configure */ int i; /* Iterate over arg-value pairs. */ Tcl_DString ds; /* DString to hold result of * calling GetThreadOption. */ if (objc < 2 || (objc % 2 == 1 && objc != 3)) { Tcl_WrongNumArgs(interp, 1, objv, "threadlId ?optionName? " "?value? ?optionName value?..."); return TCL_ERROR; } |
︙ | ︙ | |||
1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 | Tcl_Interp *interp; ClientData clientData; { ThreadClbkData *clbkPtr = (ThreadClbkData*)clientData; const char *var = (const char *)clbkPtr->clientData; Tcl_Obj *valObj; ThreadEventResult *resultPtr = &clbkPtr->result; /* * Get the result of the posted command. * We will use it to fill-in the result variable. */ valObj = Tcl_NewStringObj(resultPtr->result, -1); if (resultPtr->result != threadEmptyResult) { ckfree(resultPtr->result); } /* * Set the result variable */ if (Tcl_SetVar2Ex(interp, var, NULL, valObj, TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG) == NULL) { | > > > | > | 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 | Tcl_Interp *interp; ClientData clientData; { ThreadClbkData *clbkPtr = (ThreadClbkData*)clientData; const char *var = (const char *)clbkPtr->clientData; Tcl_Obj *valObj; ThreadEventResult *resultPtr = &clbkPtr->result; int rc = TCL_OK; /* * Get the result of the posted command. * We will use it to fill-in the result variable. */ valObj = Tcl_NewStringObj(resultPtr->result, -1); Tcl_IncrRefCount(valObj); if (resultPtr->result != threadEmptyResult) { ckfree(resultPtr->result); } /* * Set the result variable */ if (Tcl_SetVar2Ex(interp, var, NULL, valObj, TCL_GLOBAL_ONLY | TCL_LEAVE_ERR_MSG) == NULL) { rc = TCL_ERROR; goto cleanup; } /* * In case of error, trigger the bgerror mechansim */ if (resultPtr->code == TCL_ERROR) { |
︙ | ︙ | |||
1661 1662 1663 1664 1665 1666 1667 | Tcl_SetVar2Ex(interp, var, NULL, Tcl_NewStringObj(resultPtr->errorInfo, -1), TCL_GLOBAL_ONLY); ckfree((char*)resultPtr->errorInfo); } Tcl_SetObjResult(interp, valObj); Tcl_BackgroundError(interp); } | > > | | 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 | Tcl_SetVar2Ex(interp, var, NULL, Tcl_NewStringObj(resultPtr->errorInfo, -1), TCL_GLOBAL_ONLY); ckfree((char*)resultPtr->errorInfo); } Tcl_SetObjResult(interp, valObj); Tcl_BackgroundError(interp); } cleanup: Tcl_DecrRefCount(valObj); return rc; } /* *---------------------------------------------------------------------- * * ThreadCreate -- * |
︙ | ︙ | |||
2441 2442 2443 2444 2445 2446 2447 | if (resultPtr->resultMsg) { Tcl_AppendResult(interp, resultPtr->resultMsg, NULL); ckfree(resultPtr->resultMsg); } else { Tcl_AppendResult(interp, "for reasons unknown", NULL); } | | | 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 | if (resultPtr->resultMsg) { Tcl_AppendResult(interp, resultPtr->resultMsg, NULL); ckfree(resultPtr->resultMsg); } else { Tcl_AppendResult(interp, "for reasons unknown", NULL); } ckfree((char *)resultPtr); return TCL_ERROR; } if (resultPtr->resultMsg) { ckfree(resultPtr->resultMsg); } |
︙ | ︙ | |||
2674 2675 2676 2677 2678 2679 2680 | /* * Short circuit sends to ourself. */ if (thrId == Tcl_GetCurrentThread()) { Tcl_MutexUnlock(&threadMutex); if ((flags & THREAD_SEND_WAIT)) { | | | | | 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 | /* * Short circuit sends to ourself. */ if (thrId == Tcl_GetCurrentThread()) { Tcl_MutexUnlock(&threadMutex); if ((flags & THREAD_SEND_WAIT)) { int code = (*send->execProc)(interp, (ClientData)send); ThreadFreeProc((ClientData)send); return code; } else { send->interp = interp; Tcl_Preserve((ClientData)send->interp); Tcl_DoWhenIdle((Tcl_IdleProc*)ThreadIdleProc, (ClientData)send); return TCL_OK; } } |
︙ | ︙ | |||
2743 2744 2745 2746 2747 2748 2749 | Tcl_ThreadQueueEvent(thrId, (Tcl_Event*)eventPtr, TCL_QUEUE_TAIL); } Tcl_ThreadAlert(thrId); if ((flags & THREAD_SEND_WAIT) == 0) { /* * Might potentially spend some time here, until the | | > | | | > | 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 | Tcl_ThreadQueueEvent(thrId, (Tcl_Event*)eventPtr, TCL_QUEUE_TAIL); } Tcl_ThreadAlert(thrId); if ((flags & THREAD_SEND_WAIT) == 0) { /* * Might potentially spend some time here, until the * worker thread cleans up its queue a little bit. */ if ((flags & THREAD_SEND_CLBK) == 0) { while (tsdPtr->maxEventsCount && tsdPtr->eventsPending > tsdPtr->maxEventsCount) { Tcl_ConditionWait(&tsdPtr->doOneEvent, &threadMutex, NULL); } } Tcl_MutexUnlock(&threadMutex); return TCL_OK; } /* * Block on the result indefinitely. |
︙ | ︙ | |||
2902 2903 2904 2905 2906 2907 2908 | if (code != TCL_OK) { char buf[THREAD_HNDLMAXLEN]; const char *errorInfo; errorInfo = Tcl_GetVar2(tsdPtr->interp, "errorInfo", NULL, TCL_GLOBAL_ONLY); if (errorInfo == NULL) { | | | 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 | if (code != TCL_OK) { char buf[THREAD_HNDLMAXLEN]; const char *errorInfo; errorInfo = Tcl_GetVar2(tsdPtr->interp, "errorInfo", NULL, TCL_GLOBAL_ONLY); if (errorInfo == NULL) { errorInfo = Tcl_GetString(Tcl_GetObjResult(tsdPtr->interp)); } ThreadGetHandle(Tcl_GetCurrentThread(), buf); Tcl_AppendResult(interp, "Error from thread ", buf, "\n", errorInfo, NULL); } #endif |
︙ | ︙ | |||
3092 3093 3094 3095 3096 3097 3098 | interp = (sendPtr && sendPtr->interp) ? sendPtr->interp : tsdPtr->interp; if (interp != NULL) { Tcl_Preserve((ClientData)interp); if (clbkPtr && clbkPtr->threadId == thrId) { Tcl_Release((ClientData)interp); | | | 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 | interp = (sendPtr && sendPtr->interp) ? sendPtr->interp : tsdPtr->interp; if (interp != NULL) { Tcl_Preserve((ClientData)interp); if (clbkPtr && clbkPtr->threadId == thrId) { Tcl_Release((ClientData)interp); /* Watch: this thread evaluates its own callback. */ interp = clbkPtr->interp; Tcl_Preserve((ClientData)interp); } Tcl_ResetResult(interp); if (sendPtr) { |
︙ | ︙ | |||
3155 3156 3157 3158 3159 3160 3161 | */ if (code != TCL_OK) { ThreadErrorProc(interp); } ThreadSetResult(interp, code, &clbkPtr->result); | | | 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 | */ if (code != TCL_OK) { ThreadErrorProc(interp); } ThreadSetResult(interp, code, &clbkPtr->result); ThreadSend(interp, clbkPtr->threadId, tmpPtr, NULL, THREAD_SEND_CLBK); } else if (code != TCL_OK) { /* * Only pass errors onto the registered error handler * when we don't have a result target for this event. */ ThreadErrorProc(interp); |
︙ | ︙ |
Changes to generic/threadNs.c.
︙ | ︙ | |||
36 37 38 39 40 41 42 | NsThread_Init (Tcl_Interp *interp, void *cd) { NsThreadInterpData *md = (NsThreadInterpData*)cd; int ret = Thread_Init(interp); if (ret != TCL_OK) { Ns_Log(Warning, "can't load module %s: %s", md->modname, | | | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | NsThread_Init (Tcl_Interp *interp, void *cd) { NsThreadInterpData *md = (NsThreadInterpData*)cd; int ret = Thread_Init(interp); if (ret != TCL_OK) { Ns_Log(Warning, "can't load module %s: %s", md->modname, Tcl_GetString(Tcl_GetObjResult(interp))); return TCL_ERROR; } Tcl_SetAssocData(interp, "thread:nsd", NULL, (ClientData)md); return TCL_OK; } |
︙ | ︙ |
Changes to generic/threadSpCmd.c.
︙ | ︙ | |||
92 93 94 95 96 97 98 | * to pointers of their corresponding synchronization objects. */ static int initOnce; /* Flag for initializing tables below */ static Tcl_Mutex initMutex; /* Controls initialization of primitives */ static SpBucket muxBuckets[NUMSPBUCKETS]; /* Maps mutex names/handles */ static SpBucket varBuckets[NUMSPBUCKETS]; /* Maps condition variable | | | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | * to pointers of their corresponding synchronization objects. */ static int initOnce; /* Flag for initializing tables below */ static Tcl_Mutex initMutex; /* Controls initialization of primitives */ static SpBucket muxBuckets[NUMSPBUCKETS]; /* Maps mutex names/handles */ static SpBucket varBuckets[NUMSPBUCKETS]; /* Maps condition variable * names/handles */ /* * Functions implementing Tcl commands */ static Tcl_ObjCmdProc ThreadMutexObjCmd; static Tcl_ObjCmdProc ThreadRWMutexObjCmd; |
︙ | ︙ | |||
1239 1240 1241 1242 1243 1244 1245 | * *---------------------------------------------------------------------- */ static int SpCondvWait(SpCondv *condvPtr, SpMutex *mutexPtr, int msec) { | | | 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 | * *---------------------------------------------------------------------- */ static int SpCondvWait(SpCondv *condvPtr, SpMutex *mutexPtr, int msec) { Sp_AnyMutex **lock = &mutexPtr->lock; Sp_ExclusiveMutex_ *emPtr = *(Sp_ExclusiveMutex_**)lock; Tcl_Time waitTime, *wt = NULL; Tcl_ThreadId threadId = Tcl_GetCurrentThread(); if (msec > 0) { wt = &waitTime; wt->sec = (msec/1000); |
︙ | ︙ | |||
1540 1541 1542 1543 1544 1545 1546 | Tcl_MutexLock(&rmPtr->lock); if (rmPtr->owner == thisThread) { /* * We are already holding the mutex * so just count one more lock. */ | | | | | | | | | | | | | | | 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 | Tcl_MutexLock(&rmPtr->lock); if (rmPtr->owner == thisThread) { /* * We are already holding the mutex * so just count one more lock. */ rmPtr->lockcount++; } else { if (rmPtr->owner == (Tcl_ThreadId)0) { /* * Nobody holds the mutex, we do now. */ rmPtr->owner = thisThread; rmPtr->lockcount = 1; } else { /* * Somebody else holds the mutex; wait. */ while (1) { Tcl_ConditionWait(&rmPtr->cond, &rmPtr->lock, NULL); if (rmPtr->owner == (Tcl_ThreadId)0) { rmPtr->owner = thisThread; rmPtr->lockcount = 1; break; } } } } Tcl_MutexUnlock(&rmPtr->lock); return 1; } |
︙ | ︙ |
Changes to generic/threadSpCmd.h.
︙ | ︙ | |||
75 76 77 78 79 80 81 | typedef struct Sp_ReadWriteMutex_ { int lockcount; /* >0: # of readers, -1: sole writer */ int numlocks; /* Number of time the mutex got locked */ Tcl_Mutex lock; /* Regular mutex */ Tcl_ThreadId owner; /* Current lock owner thread */ /* --- */ | | | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | typedef struct Sp_ReadWriteMutex_ { int lockcount; /* >0: # of readers, -1: sole writer */ int numlocks; /* Number of time the mutex got locked */ Tcl_Mutex lock; /* Regular mutex */ Tcl_ThreadId owner; /* Current lock owner thread */ /* --- */ unsigned int numrd; /* # of readers waiting for lock */ unsigned int numwr; /* # of writers waiting for lock */ Tcl_Condition rcond; /* Reader lockers wait here */ Tcl_Condition wcond; /* Writer lockers wait here */ } Sp_ReadWriteMutex_; typedef Sp_ReadWriteMutex_* Sp_ReadWriteMutex; |
︙ | ︙ |
Changes to generic/threadSvCmd.c.
︙ | ︙ | |||
15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include "tclThreadInt.h" #include "threadSvCmd.h" #include "threadSvListCmd.h" /* Shared variants of list commands */ #include "threadSvKeylistCmd.h" /* Shared variants of list commands */ #include "psGdbm.h" /* The gdbm persistent store implementation */ /* * Number of buckets to spread shared arrays into. Each bucket is * associated with one mutex so locking a bucket locks all arrays * in that bucket as well. The number of buckets should be a prime. */ | > > > > > > > > > > > > > > > | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | #include "tclThreadInt.h" #include "threadSvCmd.h" #include "threadSvListCmd.h" /* Shared variants of list commands */ #include "threadSvKeylistCmd.h" /* Shared variants of list commands */ #include "psGdbm.h" /* The gdbm persistent store implementation */ #include "psLmdb.h" /* The lmdb persistent store implementation */ #define SV_FINALIZE /* * Names of registered persistent storage handlers. */ static const char * handlers[] = { #ifdef HAVE_GDBM "gdbm", #endif #ifdef HAVE_LMDB "lmdb", #endif }; /* * Number of buckets to spread shared arrays into. Each bucket is * associated with one mutex so locking a bucket locks all arrays * in that bucket as well. The number of buckets should be a prime. */ |
︙ | ︙ | |||
54 55 56 57 58 59 60 61 62 63 64 65 66 67 | static char *Sv_tclEmptyStringRep = NULL; /* * Global variables used within this file. */ static Bucket* buckets; /* Array of buckets. */ static Tcl_Mutex bucketsMutex; /* Protects the array of buckets */ static SvCmdInfo* svCmdInfo; /* Linked list of registered commands */ static RegType* regType; /* Linked list of registered obj types */ static PsStore* psStore; /* Linked list of registered pers. stores */ | > > > > > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | static char *Sv_tclEmptyStringRep = NULL; /* * Global variables used within this file. */ #ifdef SV_FINALIZE static size_t nofThreads; /* Number of initialized threads */ static Tcl_Mutex nofThreadsMutex; /* Protects the nofThreads variable */ #endif /* SV_FINALIZE */ static Bucket* buckets; /* Array of buckets. */ static Tcl_Mutex bucketsMutex; /* Protects the array of buckets */ static SvCmdInfo* svCmdInfo; /* Linked list of registered commands */ static RegType* regType; /* Linked list of registered obj types */ static PsStore* psStore; /* Linked list of registered pers. stores */ |
︙ | ︙ | |||
79 80 81 82 83 84 85 86 87 88 89 90 91 92 | static Tcl_ObjCmdProc SvIncrObjCmd; static Tcl_ObjCmdProc SvSetObjCmd; static Tcl_ObjCmdProc SvExistsObjCmd; static Tcl_ObjCmdProc SvGetObjCmd; static Tcl_ObjCmdProc SvArrayObjCmd; static Tcl_ObjCmdProc SvUnsetObjCmd; static Tcl_ObjCmdProc SvNamesObjCmd; /* * New commands added to * standard set of nsv_* */ static Tcl_ObjCmdProc SvPopObjCmd; | > | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | static Tcl_ObjCmdProc SvIncrObjCmd; static Tcl_ObjCmdProc SvSetObjCmd; static Tcl_ObjCmdProc SvExistsObjCmd; static Tcl_ObjCmdProc SvGetObjCmd; static Tcl_ObjCmdProc SvArrayObjCmd; static Tcl_ObjCmdProc SvUnsetObjCmd; static Tcl_ObjCmdProc SvNamesObjCmd; static Tcl_ObjCmdProc SvHandlersObjCmd; /* * New commands added to * standard set of nsv_* */ static Tcl_ObjCmdProc SvPopObjCmd; |
︙ | ︙ | |||
108 109 110 111 112 113 114 | static int DeleteContainer(Container*); static int FlushArray(Array*); static int DeleteArray(Array*); static void SvAllocateContainers(Bucket*); static void SvRegisterStdCommands(void); | < | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | static int DeleteContainer(Container*); static int FlushArray(Array*); static int DeleteArray(Array*); static void SvAllocateContainers(Bucket*); static void SvRegisterStdCommands(void); #ifdef SV_FINALIZE static void SvFinalizeContainers(Bucket*); static void SvFinalize(ClientData); #endif /* SV_FINALIZE */ static PsStore* GetPsStore(const char *handle); |
︙ | ︙ | |||
508 509 510 511 512 513 514 | if (hPtr == NULL) { PsStore *psPtr = arrayPtr->psPtr; if (psPtr) { char *val = NULL; size_t len = 0; if (psPtr->psGet(psPtr->psHandle, key, &val, &len) == 0) { tclObj = Tcl_NewStringObj(val, len); | | | 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 | if (hPtr == NULL) { PsStore *psPtr = arrayPtr->psPtr; if (psPtr) { char *val = NULL; size_t len = 0; if (psPtr->psGet(psPtr->psHandle, key, &val, &len) == 0) { tclObj = Tcl_NewStringObj(val, len); psPtr->psFree(psPtr->psHandle, val); } } if (!(flags & FLAGS_CREATEVAR) && tclObj == NULL) { return NULL; } if (tclObj == NULL) { tclObj = Tcl_NewObj(); |
︙ | ︙ | |||
1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 | * * When binding an non-existent array, we open the persistent * storage and cache all key/value pairs found there into tne * newly created shared array. */ PsStore *psPtr; size_t len; char *psurl, *key = NULL, *val = NULL; if (objc < 4) { Tcl_WrongNumArgs(interp, 2, objv, "array handle"); ret = TCL_ERROR; goto cmdExit; } | > > | 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 | * * When binding an non-existent array, we open the persistent * storage and cache all key/value pairs found there into tne * newly created shared array. */ PsStore *psPtr; Tcl_HashEntry *hPtr; size_t len; int new; char *psurl, *key = NULL, *val = NULL; if (objc < 4) { Tcl_WrongNumArgs(interp, 2, objv, "array handle"); ret = TCL_ERROR; goto cmdExit; } |
︙ | ︙ | |||
1341 1342 1343 1344 1345 1346 1347 | Tcl_AppendResult(interp, "can't open persistent storage on \"", psurl, "\"", NULL); ret = TCL_ERROR; goto cmdExit; } if (arrayPtr) { Tcl_HashSearch search; | | > | | > | 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 | Tcl_AppendResult(interp, "can't open persistent storage on \"", psurl, "\"", NULL); ret = TCL_ERROR; goto cmdExit; } if (arrayPtr) { Tcl_HashSearch search; hPtr = Tcl_FirstHashEntry(&arrayPtr->vars,&search); arrayPtr->psPtr = psPtr; arrayPtr->bindAddr = strcpy(ckalloc(len+1), psurl); while (hPtr) { svObj = Tcl_GetHashValue(hPtr); if (ReleaseContainer(interp, svObj, SV_CHANGED) != TCL_OK) { ret = TCL_ERROR; goto cmdExit; } hPtr = Tcl_NextHashEntry(&search); } } else { arrayPtr = LockArray(interp, arrayName, FLAGS_CREATEARRAY); arrayPtr->psPtr = psPtr; arrayPtr->bindAddr = strcpy(ckalloc(len+1), psurl); } if (!psPtr->psFirst(psPtr->psHandle, &key, &val, &len)) { do { Tcl_Obj * tclObj = Tcl_NewStringObj(val, len); hPtr = Tcl_CreateHashEntry(&arrayPtr->vars, key, &new); Tcl_SetHashValue(hPtr, CreateContainer(arrayPtr, hPtr, tclObj)); psPtr->psFree(psPtr->psHandle, val); } while (!psPtr->psNext(psPtr->psHandle, &key, &val, &len)); } } else if (index == AUNBIND) { if (arrayPtr && arrayPtr->psPtr) { PsStore *psPtr = arrayPtr->psPtr; if (psPtr->psClose(psPtr->psHandle) == -1) { |
︙ | ︙ | |||
2011 2012 2013 2014 2015 2016 2017 | /* * Syntax: * * tsv::lock array arg ?arg ...? */ if (objc < 3) { | | | | 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 | /* * Syntax: * * tsv::lock array arg ?arg ...? */ if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "array arg ?arg...?"); return TCL_ERROR; } arrayPtr = LockArray(interp, Tcl_GetString(objv[1]), FLAGS_CREATEARRAY); bucketPtr = arrayPtr->bucketPtr; /* * Evaluate passed arguments as Tcl script. Note that |
︙ | ︙ | |||
2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 | * since it needs the array which may be unset by the script. */ UNLOCK_BUCKET(bucketPtr); return ret; } /* *----------------------------------------------------------------------------- * * Sv_RegisterStdCommands -- * * Register standard shared variable commands | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 | * since it needs the array which may be unset by the script. */ UNLOCK_BUCKET(bucketPtr); return ret; } /* *----------------------------------------------------------------------------- * * SvHandlersObjCmd -- * * This procedure is invoked to process "tsv::handlers" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * None. * *----------------------------------------------------------------------------- */ static int SvHandlersObjCmd( ClientData arg, /* Not used. */ Tcl_Interp *interp, /* Current interpreter. */ int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { /* * Syntax: * * tsv::handlers */ if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewStringObj( Tcl_Merge(sizeof(handlers)/sizeof(handlers[0]), handlers), -1)); return TCL_OK; } /* *----------------------------------------------------------------------------- * * Sv_RegisterStdCommands -- * * Register standard shared variable commands |
︙ | ︙ | |||
2076 2077 2078 2079 2080 2081 2082 | SvRegisterStdCommands(void) { static int initialized = 0; if (initialized == 0) { Tcl_MutexLock(&initMutex); if (initialized == 0) { | | | | | | | | | | | | | | > | 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 | SvRegisterStdCommands(void) { static int initialized = 0; if (initialized == 0) { Tcl_MutexLock(&initMutex); if (initialized == 0) { Sv_RegisterCommand("var", SvObjObjCmd, NULL, 1); Sv_RegisterCommand("object", SvObjObjCmd, NULL, 1); Sv_RegisterCommand("set", SvSetObjCmd, NULL, 0); Sv_RegisterCommand("unset", SvUnsetObjCmd, NULL, 0); Sv_RegisterCommand("get", SvGetObjCmd, NULL, 0); Sv_RegisterCommand("incr", SvIncrObjCmd, NULL, 0); Sv_RegisterCommand("exists", SvExistsObjCmd, NULL, 0); Sv_RegisterCommand("append", SvAppendObjCmd, NULL, 0); Sv_RegisterCommand("array", SvArrayObjCmd, NULL, 0); Sv_RegisterCommand("names", SvNamesObjCmd, NULL, 0); Sv_RegisterCommand("pop", SvPopObjCmd, NULL, 0); Sv_RegisterCommand("move", SvMoveObjCmd, NULL, 0); Sv_RegisterCommand("lock", SvLockObjCmd, NULL, 0); Sv_RegisterCommand("handlers", SvHandlersObjCmd, NULL, 0); initialized = 1; } Tcl_MutexUnlock(&initMutex); } } /* |
︙ | ︙ | |||
2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 | { int i; Bucket *bucketPtr; SvCmdInfo *cmdPtr; const Tcl_UniChar no[3] = {'n', 'o', 0} ; Tcl_Obj *obj; /* * Add keyed-list datatype */ TclX_KeyedListInit(interp); Sv_RegisterKeylistCommands(); | > > > > > > > > > > > > > > | 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 | { int i; Bucket *bucketPtr; SvCmdInfo *cmdPtr; const Tcl_UniChar no[3] = {'n', 'o', 0} ; Tcl_Obj *obj; #ifdef SV_FINALIZE /* * Create exit handler for this thread */ Tcl_CreateThreadExitHandler(SvFinalize, NULL); /* * Increment number of threads */ Tcl_MutexLock(&nofThreadsMutex); ++nofThreads; Tcl_MutexUnlock(&nofThreadsMutex); #endif /* SV_FINALIZE */ /* * Add keyed-list datatype */ TclX_KeyedListInit(interp); Sv_RegisterKeylistCommands(); |
︙ | ︙ | |||
2180 2181 2182 2183 2184 2185 2186 | * Create array of buckets and initialize each bucket */ if (buckets == NULL) { Tcl_MutexLock(&bucketsMutex); if (buckets == NULL) { buckets = (Bucket *)ckalloc(sizeof(Bucket) * NUMBUCKETS); | < < > > > > | 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 | * Create array of buckets and initialize each bucket */ if (buckets == NULL) { Tcl_MutexLock(&bucketsMutex); if (buckets == NULL) { buckets = (Bucket *)ckalloc(sizeof(Bucket) * NUMBUCKETS); for (i = 0; i < NUMBUCKETS; ++i) { bucketPtr = &buckets[i]; memset(bucketPtr, 0, sizeof(Bucket)); Tcl_InitHashTable(&bucketPtr->arrays, TCL_STRING_KEYS); Tcl_InitHashTable(&bucketPtr->handles, TCL_ONE_WORD_KEYS); } /* * There is no other way to get Sv_tclEmptyStringRep * pointer value w/o this trick. */ { Tcl_Obj *dummy = Tcl_NewObj(); Sv_tclEmptyStringRep = dummy->bytes; Tcl_DecrRefCount(dummy); } /* * Register persistent store handlers */ #ifdef HAVE_GDBM Sv_RegisterGdbmStore(); #endif #ifdef HAVE_LMDB Sv_RegisterLmdbStore(); #endif } Tcl_MutexUnlock(&bucketsMutex); } return TCL_OK; } |
︙ | ︙ | |||
2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 | { register int i; SvCmdInfo *cmdPtr; RegType *regPtr; Tcl_HashEntry *hashPtr; Tcl_HashSearch search; /* * Reclaim memory for shared arrays */ if (buckets != NULL) { Tcl_MutexLock(&bucketsMutex); | > > > > > > > > > > > > | 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 | { register int i; SvCmdInfo *cmdPtr; RegType *regPtr; Tcl_HashEntry *hashPtr; Tcl_HashSearch search; /* * Decrement number of threads. Proceed only if I was the last one. The * mutex is unlocked at the end of this function, so new threads that might * want to register in the meanwhile will find a clean environment when * they eventually succeed acquiring nofThreadsMutex. */ Tcl_MutexLock(&nofThreadsMutex); if (nofThreads > 1) { goto done; } /* * Reclaim memory for shared arrays */ if (buckets != NULL) { Tcl_MutexLock(&bucketsMutex); |
︙ | ︙ | |||
2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 | ckfree((char*)regPtr); regPtr = tmpPtr; } regType = NULL; } Tcl_MutexUnlock(&svMutex); } #endif /* SV_FINALIZE */ /* EOF $RCSfile: threadSvCmd.c,v $ */ /* Emacs Setup Variables */ /* Local Variables: */ /* mode: C */ /* indent-tabs-mode: nil */ /* c-basic-offset: 4 */ /* End: */ | > > > > | 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 | ckfree((char*)regPtr); regPtr = tmpPtr; } regType = NULL; } Tcl_MutexUnlock(&svMutex); done: --nofThreads; Tcl_MutexUnlock(&nofThreadsMutex); } #endif /* SV_FINALIZE */ /* EOF $RCSfile: threadSvCmd.c,v $ */ /* Emacs Setup Variables */ /* Local Variables: */ /* mode: C */ /* indent-tabs-mode: nil */ /* c-basic-offset: 4 */ /* End: */ |
Changes to generic/threadSvCmd.h.
︙ | ︙ | |||
85 86 87 88 89 90 91 | typedef int (ps_get_proc) (ClientData, const char*, char**, size_t*); typedef int (ps_put_proc) (ClientData, const char*, char*, size_t); typedef int (ps_first_proc) (ClientData, char**, char**, size_t*); typedef int (ps_next_proc) (ClientData, char**, char**, size_t*); typedef int (ps_delete_proc)(ClientData, const char*); typedef int (ps_close_proc) (ClientData); | | | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | typedef int (ps_get_proc) (ClientData, const char*, char**, size_t*); typedef int (ps_put_proc) (ClientData, const char*, char*, size_t); typedef int (ps_first_proc) (ClientData, char**, char**, size_t*); typedef int (ps_next_proc) (ClientData, char**, char**, size_t*); typedef int (ps_delete_proc)(ClientData, const char*); typedef int (ps_close_proc) (ClientData); typedef void(ps_free_proc) (ClientData, void*); typedef const char* (ps_geterr_proc)(ClientData); /* * This structure maintains a bunch of pointers to functions implementing * the simple persistence layer for the shared variable arrays. */ |
︙ | ︙ |
Changes to generic/threadSvListCmd.c.
︙ | ︙ | |||
842 843 844 845 846 847 848 | Tcl_WrongNumArgs(interp, off, objv, "index ?index...? value"); goto cmd_err; } lPtr = svObj->tclObj; argc = objc - off - 1; | | | 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 | Tcl_WrongNumArgs(interp, off, objv, "index ?index...? value"); goto cmd_err; } lPtr = svObj->tclObj; argc = objc - off - 1; if (!SvLsetFlat(interp, lPtr, argc, (Tcl_Obj**)objv+off,objv[objc-1])) { return TCL_ERROR; } Tcl_SetObjResult(interp, Sv_DuplicateObj(lPtr)); return Sv_PutContainer(interp, svObj, SV_CHANGED); |
︙ | ︙ |
Changes to lib/ttrace.tcl.
︙ | ︙ | |||
69 70 71 72 73 74 75 | interp alias {} [namespace current]::_set {} tsv::set interp alias {} [namespace current]::_unset {} tsv::unset } else { error "requires NaviServer/AOLserver or Tcl threading extension" } # Keep in sync with the Thread package | | | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | interp alias {} [namespace current]::_set {} tsv::set interp alias {} [namespace current]::_unset {} tsv::unset } else { error "requires NaviServer/AOLserver or Tcl threading extension" } # Keep in sync with the Thread package package provide Ttrace 2.8.0 # Package variables variable resolvers "" ; # List of registered resolvers variable tracers "" ; # List of registered cmd tracers variable scripts "" ; # List of registered script makers variable enables "" ; # List of trace-enable callbacks variable disables "" ; # List of trace-disable callbacks |
︙ | ︙ |
Added tests/French.txt.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 | ########################################################################### #Copyright 1999 The Internet Dictionary Project/Tyler Chambers #http://www.june29.com/IDP/ #This file is free to use and modify. Thank you for using the IDP. # #Approximately 1340 entries. 9/21/97 #Approximately 1884 entries. 1/7/98 #Appriximately 2160 entries. 3/8/98 #Approximately 3040 entries. 8/18/98 #Approximately 3250 entries. 2/19/99 ########################################################################### a un(e): ~ book = un livre. 2.(instead of number one) ~ year ago; il y a un an[Article] a un, une[Pronoun] aardvark orycte/rope[Noun] aardvark adverbe[Adverb] aardvarks tamanoirs aback etre deconcerte[Verb] aback to be taken ~ : etre deconcerte,interdit[Adverb] aback to be taken ~ :etre stupefait(e)[Adjective] abacterial non-bacte/rien[Adjective] abacus abaque,boulier (compteur)[Noun] abacus abaque[Noun] abacus boulier,compteur[Noun] abacuses abaques, bouliers abacuses abaques[Noun] abacuses bouliers, compteurs[Noun] abaft sur l'arrie\re, vers l'arrie\re[Adverb] abalone ormeau[Noun] abalones ormeaux[Noun] abandon abandon, laisser-aller[Noun] abandon abandonner[Verb] abandoned abandonne/[Adjective] abandoned abandonnes[Adjective] abandoned de/vergonde/[Adjective] abandonee abandoned, forsaken[Adjective] abandoner abandoneur[Adjective] abandoning abandonnant[Verb] abandonment abandon[Noun] abandonment abandonnement[Noun] abandonments abandons[Noun] abandons abandonnes[Verb] abase abaisser, humilier[Verb] abased humilie/ abasement abaissement, humiliation[Noun] abasements abaissement[Noun] abases mortifie, humilie, rabaisse[Verb] abash confondre, de/concerter[Verb] abashed confus(e), embarrasse(e)[Adjective] abashed deconcerte, confus, gene[Adjective] abasing humiliant[Adjective] abate diminuer[Verb] abate s'apaiser, se calmer[Verb] abated a diminue/[Verb] abatement diminution[Noun] abatement la suppression[Noun] abatements coupures abates se calme, s'apaise[Verb] abating faiblant[Adjective] abating faiblant[Adjective] abattoir abattoir[Noun] abbe abbe/[Noun] abberations aberrations[Noun] abbey abbaye (f)[Noun] abbey une abbaye[Noun] abbeys abbayes[Noun] abbot abbe ( d'un monastere)[Noun] abbot abbe/ abbot abbe/[Noun] abbot pere superieur[Noun] abbot abbe/[Noun] abbots abbe/s[Noun] abbreviate abbre/ger[Verb] abbreviate abre/ger[Verb] abbreviated abbre/gé[Verb] abbreviates s'abre\ge[Verb] abbreviating abre/geant[Verb] abbreviation abbre/viation[Noun] abbreviation abre/viation[Noun] abbreviation abreviation (f)[Noun] abbreviations abbre/viations[Noun] abbreviations abre/viations[Noun] abbreviator abre/viateur[Noun] abdicable abdiquable[Adjective] abdicate abdiquer[Verb] abdicate renoncer[Verb] abdicated abdique/[Adjective] abdication abdication[Verb] abdicator abdicateur[Adjective] abdomen abdomen (m)[Noun] abdomen abdomen[Noun] abdomens abdomens[Noun] abdominal abdominal[Adjective] abdominally abdominalement[Adverb] abduct enlever[Verb] abducted enlevé[Verb] abducting enlevant[Verb] abduction enlèvement[Noun] abductions enlèvements[Noun] abductor adducteur[Adjective] abductors adducteur[Adjective] abducts detourner[Verb] abeam par le travers[Adverb] abecedarian abécédaire[Noun] abed au lit[Noun] aberrance aberration (f)[Noun] aberrant aberrant, egare[Adjective] aberrantly de fac,on aberrante[Adverb] aberration aberration[Noun] aberration anomalie (f)[Noun] aberrations erreurs abet encourager (au crime)[Verb] abetment encouragement[Noun] abets secourirs abetted encouragea, soutient[Verb] abetter complice[Noun] abetting provoquant[Adjective] abettor aide, complice[Noun] abeyance in ~ (law): en desuetude; (matter) en suspens[Noun] abeyant en attente[Adjective] abhor avoir horreur de[Verb] abhorred abhorrait or abhorre/, de/testait or de/teste/[Verb] abhorrence aversion extreme, horreur[Noun] abhorrent odieux abhorrently de fac,on odieuse[Adverb] abhorring abhorrant[Adjective] abhors abhorrer[Verb] abide i can't ~ it/him : je ne peut pas le souffrir <or> supporter; to ~ by : observer, respecter[Verb] abided souffri[Adjective] abides tole\re, demeure, subsiste[Verb] abiding constant, e/ternel[Adjective] abilities talents[Noun] ability compe/tence ability competence (f); capacite (f); (skill) talent (m)[Noun] abiotic abiotique[Adjective] abject (poverty) sordid; (apology) plat(e)[Adjective] abjection abjection(f)[Noun] abjectly avec servilite/[Adjective] abjuration renoncement, apostasie (rel)[Noun] abjure abjurer[Verb] abjurer personne qui abjure ablation ablation ablative ablatif[Adjective] ablaze en feu ablaze en feu, en flammes[Adjective] able compe/tent(e) able competent(e); to be ~ to do sth : pouvoir faire qch, etre capable de faire qch[Adjective] able capable -to be able to e^tre capable de , pouvoir able to be ~: pouvoir[Verb] abler plus compétent(e)[Adjective] ablest le plus compe/tent[Adjective] abloom en fleur ablution ablution[Noun] ablutions ablutions[Noun] ably de fac,on compe/tente, habilement[Adjective] abnegate Renouncer à [Verb] abnegates renie, re/pudie, rejette[Verb] abnegation abne/gation[Noun] abnormal abnormal(e)[Adjective] abnormal anormal(e)[Adjective] abnormal anormal abnormalities anomalies, difformite/s[Noun] abnormality anomalie, malformation[Noun] abnormally anormalement[Adverb] aboard a\ bord abode of no fixed ~ :sans domicile fixe[Noun] abodes demeures, domiciles[Noun] aboil en train de bouillir[Verb] abolish abolir[Verb] abolish abroger, supprimer[Verb] abolishable qui peut e^tre aboli abolished aboli(es)[Verb] abolisher suppresseur[Adjective] abolishes abolit, abroge, supprime abolishment suppression, abolition, abrogation[Noun] abolition abolition abolition suppression[Noun] abolitionism abolitionnisme[Noun] abolitionist abolitionniste[Adjective] abolitionists abolitionnistes, antiesclavagistes (hist)[Noun] abominable abominable[Adjective] abominably abominablement, odieusement[Adverb] abominate abhorrer, exe/crer, abominer[Verb] abomination abomination[Noun] abominations abominations[Noun] aboriginal aborige\ne[Noun] aboriginally aboriginalement[Adverb] aborigine aborigene m/f[Noun] aborigines aborigines[Noun] abort faire avorter[Verb] aborted avorté[Verb] aborter avorteur/ avorteuse / faiseuse d'anges[Noun] aborting discontinuant[Adjective] abortion avortement abortion avortement (m)[Noun] abortionist avorteur[Noun] abortionists avorteurs abortions avortements[Noun] abortive manque(e)[Adjective] abortively en vain[Verb] aborts avorte, e/choue, abandonne[Verb] abound abonder abounding abondant[Adjective] about (approximatly)environ, a peu pres[Adjective] above au-dessus[Adjective] aboveboard re/gulier, correct[Adjective] aboveground au-dessus du sol, a\ la surface[Adjective] abovementioned ci-haut mentionné abovementioned mentionné ci-dessus[Adjective] abracadabra abracadabra[Verb] abradable qui peut s'e/rafler, qui peut s'e/roder[Adjective] abrade user en frottant, e/roder[Verb] abrasion frottement, e/corchure, abrasion[Noun] abrasions écorchures, égratignures[Noun] abrasive abrasif(ive)[Adjective] abrasives abrasifs[Noun] abreast de front[Adjective] abridge abreger[Verb] abridged abre/ge/[Verb] abridgement re/sume/[Noun] abridging raccourc,ant[Adjective] abroad a\ l'e/tranger, au loin[Adverb] abrogate abroger[Verb] abrogated abroge/, aboli[Verb] abrogation abrogation[Noun] abrupt abrupte[Adjective] abruptly brusquement[Adjective] abruptness abrupte[Noun] abscess abcès[Noun] abscesses abce\s[Noun] abscond s'enfuir[Verb] absconded s'enfuir (from, de)[Verb] absence absence[Noun] absences absences[Noun] absent absent[Adjective] absentee absentee[Noun] absenteeism absente/isme[Noun] absentees absentees[Noun] absently distraitement[Adverb] absentminded distrait[Adjective] absentmindedly d'un air distrait[Adverb] absentmindedly distraitement[Adverb] absentmindedness distraction[Noun] absinth absinthe[Noun] absinthe absinthe[Noun] absolute absolu[Adjective] absolutely absolument[Adverb] absolution absolution[Noun] absolutism absolutisme[Noun] absolve absoudre[Verb] absolved exone/re/[Adjective] absolving exon/erant[Adjective] absorb absorber, retenir, assimiler[Verb] absorbability absorbabilite/[Adjective] absorbable absorbable[Adjective] absorbant absorbant[Adjective] absorbed absorb/e[Adjective] absorbent absorbant(e)[Adjective] absorbing absorbant[Adjective] absorption absorbtion[Noun] abstain abstenir[Verb] abstained absteni[Adjective] abstemious frugal(e), sobre[Adjective] abstention abstention[Noun] abstentions abstentions[Noun] abstinence abstinence[Noun] abstinent sobre[Adjective] abstinently sobrement[Adverb] abstract abstrait[Adjective] abstract résumé, abrégé[Noun] abstraction distraction, abstraction[Noun] abstruse abstrus(e)[Adjective] absurd absurde[Adjective] absurdism absurdisme[Noun] absurdist absurdiste[Noun] absurdities absurdite/s[Noun] absurdity absurdite/[Noun] abundance abondance[Noun] abundant abondant[Adjective] abundantly abondamment[Adjective] abuse abus[Noun] abused abuse/[Verb] abused insulter[Verb] abusive abusif[Adjective] abusively abusivement[Adverb] abut etre contigu(ë) à [Verb] abuzz bourdonnant[Adjective] abysmal épouvantable, abominable[Noun] abysmally abominablement[Adverb] abyss abysse[Noun] abyss abi^me[Noun] abysses abysses[Noun] abysses abi^mes[Noun] acacia acacia[Noun] academic académique[Adjective] academical acade/mique[Adjective] academically acade/miquement[Adverb] academician acade/micien[Noun] academies academies[Noun] academism academisme[Noun] academy académie[Noun] acanthus acanthe[Noun] acanthuses acanthes[Noun] accede acce/der[Verb] accede consentir[Verb] accelerate acce/le/rer[Verb] accelerated accéléré[Adjective] acceleration acce/le/ration[Noun] accelerations acce/le/rations[Noun] accelerator acce/le/rateur[Noun] accelerators acce/le/rateurs[Noun] accelerometer acce/le/rome\tre[Noun] accelerometers acce/le/rome\tres[Noun] accent accent[Noun] accented accente/[Verb] accented accentue/ accents accents[Noun] accentual accentuelle[Adjective] accentually accentuellement[Adverb] accentuate accentuer[Verb] accentuated accentue/[Adjective] accentuation accentuation[Noun] accept accepter[Verb] acceptability acceptabilite/[Noun] acceptable acceptable[Adjective] acceptably convenablement[Adverb] acceptance acceptation[Noun] accepted accepte/[Verb] accepter accepteur[Noun] acceptor accepteur[Noun] access acce\s, acce/der (verb)[Noun] accessed accesse/[Verb] accessibility accessibilite/[Noun] accessible accessible[Adjective] accession accession[Noun] accessorial accessoire[Adjective] accessories accessoires[Noun] accessorize accessoriser[Verb] accessors accesseurs[Noun] accessory accessoire[Noun] accident accident[Noun] accidental accidentel[Adjective] accidentalism accidentalisme[Noun] accidentalist accidentaliste[Noun] accidentally accidentellement[Adverb] accidently accidentalement[Adverb] accidents accidents[Noun] acclaim acclamer[Verb] acclamation acclamation[Noun] acclimate acclimater[Verb] acclimated acclimate/[Adjective] acclimatize acclimater[Verb] accolade accolade[Noun] accolades accolades[Noun] accommodate accomoder[Verb] accommodated accommode/[Verb] accommodating obligeant(e)[Adjective] accommodation accomodation[Noun] accommodations accommodations[Noun] accompanied accompagne/[Adjective] accompanier accompagneur[Noun] accompanies accompanies[Verb] accompaniment accompagnement[Noun] accompaniments accompagnements[Noun] accompanist accompaniste[Noun] accompanists accompanistes[Noun] accompany accompagner, accompagner qqn (à )[Verb] accompanyist accompagnateur[Noun] accompanyists accompagnateurs[Noun] accomplice complice[Noun] accomplices complices[Noun] accomplish accomplir[Verb] accomplished accompli(e)[Adjective] accomplishment accomplissement[Noun] accomplishments accomplissements[Noun] accord accord[Noun] accordance in accordance with : en conformite/ avec accorder accordeur[Noun] accorders accordeurs[Noun] accordion accorde/on[Noun] accordionist accordionist accordioniste[Noun] accordionists accordionists accordionistes[Noun] accordions accorde/ons[Noun] accords accords[Noun] accost accoster[Verb] account compte[Noun] accountability responsibilité[Noun] accountable responsable[Adjective] accountant comptable[Noun] accounting comptabilité accouterment accoutrement[Noun] accredited accredite/[Verb] accrued accrue/[Verb] accruement accruement[Noun] accumulated accumule/[Verb] acetaminophen ace/taminophe\n[Noun] acetify acetifie/[Verb] acetone acetone[Noun] acid acide[Noun] acidic acidique[Adjective] admission aveu[Adverb] allergen allergene allergen allergene[Noun] allergic alergique[Adjective] allergies allergies allergies allergies[Noun] allergy allergie allergy allergie[Noun] alleviate apaiser, soulager[Verb] alleviated apaise/, apaise/e[Adjective] alley ruelle, alle/e alley ruelle, allée[Noun] alleys ruelles, alle/es alleys ruelles, alle/es[Noun] alliance alliance alliance alliance[Noun] alliances alliances alliances alliances[Noun] allied allie/, allie/e allied allie/, allie/e[Adjective] alligator alligator alligator alligator[Noun] alligators alligators alligators alligators[Noun] alliteration allite/ration alliteration allite/ration[Noun] alliterations allite/rations alliterations allite/rations[Noun] allocate attribuer[Verb] allocated attibue/, attribue/e[Adjective] allocation attribution allocation attribution[Noun] allocations attibutions allocations attributions[Noun] allocution allocution allocution attribution[Noun] allocution allocution[Noun] allot assigner[Verb] allow autoriser, permettre[Verb] allowable admissible[Adjective] allowance indemnité[Noun] allowed autorise/, autorise/e[Adjective] alloy alliage[Noun] alphabet alphabet[Noun] alphabetic alphabetique[Adjective] alphabetical alphabetique[Adjective] alphabetically alphabetiquement[Adverb] alphabetization alphabetisation[Noun] alphabetizations alphabetisations[Noun] alphabetize alphabetiser[Verb] alphabetized alphabetise[Adjective] alphabetizing alphabetizer[Verb] alphabets alphabets[Noun] alphamerical alphanumerique[Adjective] alphanumeric alphanumerique[Noun] alphanumerical alphanumerique[Adjective] alphanumerically alphanumeriquement[Adverb] alphanumerics alphanumerique[Adverb] alpine alpin[Adjective] alpinism alpinisme[Noun] alpinist alpiniste[Noun] already deja[Conjunction] also aussi[Conjunction] altercation altercation[Noun] altercations altercations[Noun] alternate alterner[Verb] alternated alterne[Adjective] alternately alternativement[Adverb] among parmi, entre[Preposition] amoral amoral[Adjective] amorous amoureux[Adjective] amorously amoureusement, avec amour[Adverb] amorphous amorphe[Adjective] amount s'elever. monter[Verb] amount somme, quantite, importance[Noun] amp ampere ; amplifier[Noun] ampere ampere[Noun] ampersand et commercial ; esperluette[Noun] amphetamine amphetamine[Noun] and et[Preposition] anyway En tout cas, de toute facon[Adverb] anywhere n'importe ou ; partout[Adverb] aorta aorte[Noun] apace rapidement[Adverb] apart a part, separe[Adjective] apartheid apartheid[Noun] apartment apartement, chambre[Noun] apathetic apathique[Adjective] apathy apathie, indifference[Noun] ape singe[Noun] ape singer[Verb] aperitif aperitif[Noun] aperture ouverture[Noun] apex sommet[Noun] aphid aphis; puceron[Noun] arrive arrivant[Verb] aspen abedul audit audit[Noun] auditorium auditorium[Noun] auditoriums auditoriums[Noun] audits audits[Verb] available disponible babble bavard[Verb] babbler bavardent babies be/be/s[Noun] baboon babouin baby be/be/[Noun] baccalaureate baccalaure/at[Noun] baccarat baccarat[Noun] bachelor ce/libataire[Noun] bachelors ce/le/bataires[Noun] bacilli bacilles (noun masculine)[Noun] bacillus bacille (noun masculine)[Noun] back en arriere, en retour backache douler de dos backbite calumnier backbone e/pine[Noun] background arriere-plan backgrounds arriere-plans backside derrie\re[Noun] backslide re/gresser[Verb] backup (computer) sauvegarde (feminine)[Noun] backward en arrie\re[Preposition] bacon lard bacteria bactérie bad mauvais, torve badge insigne badged insignée badgers blaireaux badinage badinage bag sac[Noun] bagatelle bagatelle bagatelles bagatelles baggage effets, colis bags fouilles, étuis, sacs baguette baguette bah bannir[Verb] bail caution bairn enfant (e/cossais)[Noun] bait leurre, eche bake faire cuire[Verb] baker boulanger bakeries boulangeries bakers boulangers bakery boulangerie bakeshop boulangerie[Noun] balance balance, équilibrer balconies balcons balcony balcon bald chauve, à ras baldhead chauve[Adjective] baldly ouvertement[Adverb] baldness calvitie[Noun] bale ballot baleen baleine balk déjouer[Verb] ball bal (dance), ballon (like for games) ballad ballade ballade ballade ballads ballades ballast ballast, lest ballet ballet balletic balletique balloon ballon, aérostat ballot ballot balls bals[Noun] ballyhoo publicite/[Noun] balm baume[Noun] bamboo enfant (italien)[Noun] bamboozle tricher[Verb] banana banane bananas bananes band bande, chapelle bandage bandage bandeau bandeau bandit brigand, forban, bandit bandits brigands, forbans, bandits bandleader chef d'orchestre[Noun] bandmaster chef d'orchestre[Noun] bane poison[Noun] banished banni[Adjective] barb barbe[Noun] barbarian barbare[Noun] barbarians barbares[Noun] barbarism barbarisme[Noun] barber barbier[Noun] barmaid serveuse[Noun] barman serveur[Noun] barracks casernes[Noun] beach plage[Noun] bear ours[Noun] bear supporter[Verb] bed lit[Noun] bedroom chambre (a coucher)[Noun] believe croire[Verb] betray trahir[Verb] bibliographic bibliographique[Adjective] bibliographies bibliographies[Noun] bibliography bibliographie[Noun] blackberry zarzamorra[Noun] bonjour hello book livre (m) boomerang boomerang (m) boxer (~ shorts) caleçon[Noun] boy garc,on[Noun] boys garc,ons[Noun] brain cerveaux[Noun] brood rimuginare, covare[Verb] broom balai broth bouillon build construire[Verb] building ba^timent[Noun] bye bon voyage, ciao[Preposition] cab taxi[Noun] cabal cabale[Noun] cabala cabale[Noun] cabalism cabalisme[Noun] cabalist cabaliste[Noun] cabalistic cabalistique[Adjective] caballero cavalier[Noun] cabaret cabaret[Noun] cabbage chou[Noun] cabbages choux[Noun] cabdriver chauffeur de taxi[Noun] cabin cabane[Noun] cabinet cabinet[Noun] cabinetmaker e/be/niste[Noun] cabinetmakers e/be/nistes[Noun] cabinets cabinets[Noun] cabins cabanes,(ships)cabines[Noun] cable ca^ble[Noun] cabled cablé[Adjective] cablegram ca^blogramme[Noun] cablegrams ca^blogrammes[Noun] cables ca^bles[Noun] cabling cablage[Noun] cabman cocher de fiacre[Noun] caboose caboose[Noun] cabotage cabotage[Noun] cabriolet cabriolet[Noun] cabs taxis[Noun] cacao cacao[Noun] cacciatore chasseur[Noun] cachalot cachalot[Noun] cache cachette[Noun] cachepot cachepot[Noun] caches cachettes[Noun] cackle caquet[Noun] cackled caquete/[Verb] cackles caquets[Noun] cackling caquetant[Verb] cacophony cacophonie[Noun] cacti cactus(plural)[Noun] cactus cactus (singular)[Noun] cad mufle[Noun] cadaver cadavre cadaverous terreux,[Adjective] caddies boi^tes a\ the/[Noun] caddy boii^te a\ the/[Noun] cadence cadence[Noun] cadet cadet, younger son[Noun] cadetship brevet de cadet[Noun] cadge mendier[Verb] cadger mendiant[Noun] cafe cafe/-restaurant[Noun] cafes cafe/-restaurants[Noun] cafeteria cafe/taria[Noun] cafeterias cafe/tarias[Noun] caffeine cafe/ine[Verb] caftan caftan[Noun] cage cage[Noun] cages cages[Noun] cahier copy book[Noun] cairn cairn[Noun] cairns cairns[Noun] caitiff la^che[Adjective] cajole cajoler[Verb] cajoler cajoleur[Noun] cajolery cajolerie[Noun] cake gâteau[Noun] cake ga^teau[Noun] calcium calcium[Noun] calculate calculer[Verb] calculated calculé calibrate calibrer[Verb] calibrated calibré[Adjective] calibration calibration[Noun] car voiture[Noun] carbonization carbonisation[Noun] carbonize carboniser[Verb] carbonized carbonise[Adjective] carbonless sans carbone[Adjective] carburetor carburateur[Noun] carburetors carburateurs[Noun] carburization carburation[Noun] carburize carburer[Verb] card carte[Noun] cardamom cardamone[Noun] cardiac cardiaque[Adjective] cardigan cardigan[Noun] cardioid cardioide[Noun] cardioids cardioides[Noun] care attention[Noun] care care[Noun] cared attentionne[Adjective] career cariere[Noun] careful attentionne[Adjective] carefully avec attention[Adjective] cat le chat[Noun] cell cellule[Noun] cellular cellulaire[Adjective] chance hasard cherries les cerises[Noun] church e/glise[Noun] churches e/glises[Noun] cloak manteau[Noun] cloaks manteaux[Noun] clock horloge[Noun] clockmaker horloger[Noun] clockwise dans le sens des aigu.illes d'une montre cloister cloitre[Noun] clone clone[Noun] cloud le nuage c'mon ben voyons coal charbon (masc.)[Noun] computer ordinateur[Noun] computers ordinateurs[Noun] comrades amis[Noun] concealed e/touffe/ conjuring escamotage[Verb] contemplate contempler[Verb] contemplate envisager[Verb] contemplate pre/voir[Verb] contemplates envisage[Verb] contemplation contemplation[Noun] contemplation me/ditation[Noun] contemplation recueillement[Noun] contemplations contemplations[Noun] contemplations me/ditations[Noun] contemplative contemplatif[Adjective] contemporaneous contemporain[Adjective] contemporaneously en me^me temps que [Adverb] contemporaries contemporains[Noun] contemporaries de la me^me ge/ne/ration[Adjective] contemporary contemporain[Adjective] contemporary de la me^me ge/ne/ration[Adjective] contempt de/dain[Noun] contempt me/pris[Noun] contemptible indigne[Adjective] contemptible me/prisable[Adjective] contemptibly avec me/pris[Adverb] contemptuous de me/pris[Adjective] contemptuous me/prisant[Adjective] contemptuously avec de/dain[Adverb] contemptuously avec me/pris[Adverb] contend combattre[Verb] contend disputer[Verb] contend lutter[Verb] contender candidat[Noun] contender challenger[Noun] contender concurrent[Noun] contenders candidats[Noun] contenders challengers[Noun] contenders concurrents[Noun] contending concurrents[Adjective] contending oppose/es[Adjective] contends dispute[Verb] contends lutte[Verb] content contenter[Verb] content satisfaire[Verb] content satisfait[Adjective] contented content[Adjective] contented satisfait[Adjective] contentedly avec contentement[Adverb] contentedness contentement[Noun] contention dispute[Noun] contention e/mulation[Noun] contention lutte[Noun] contentions disputes[Noun] contentions e/mulations[Noun] contentions luttes[Noun] contentious contentieux[Adjective] contentious querelleur[Adjective] contentment contentement[Noun] contents contenu[Noun] contents table de matie\res[Noun] contest combat[Noun] contest concours[Noun] contest contester[Verb] contestant combattant[Noun] contestant concurrent[Noun] cot lit d'enfant[Noun] coterie coterie[Noun] cotillion cotillon[Noun] cotillon cotillon[Noun] cottage chaumie\re[Noun] cottager paysan[Noun] couch couche[Noun] cough tousser[Verb] coughs toux[Noun] count compter[Verb] countenance visage[Noun] counteract neutraliser[Verb] counterbalance contrepoids[Noun] counterfeit contrefait[Adjective] countermand contremander[Verb] countermarch contremarche[Noun] counterplot contre-ruse[Noun] counterpoint contrepoint[Noun] counterpoise contre-balancer[Verb] counterweight contrepoids[Noun] countess comtesse[Noun] countless innombrable[Adjective] country pays[Verb] countryman concitoyen[Noun] countrywide concitoyenne county comte/[Noun] couple couple[Noun] couplet distique[Noun] coupon coupon[Noun] courage courage[Noun] courageous courageux[Adjective] courageously cougrageusement[Adjective] courier courrier[Noun] course cours[Noun] courser coursier[Noun] court cour[Noun] courteous courtois[Adjective] courteously courtoisement[Adverb] courteousness courtoisie[Noun] courtesy courtoisie courthouse palais de justice[Noun] courtier courtisan[Noun] courtliness e/le/gance[Adjective] courtly e/le/gant[Adjective] courtmartial conseil de guerre[Noun] courtroom salle d'audience[Noun] courtship cour[Noun] cousin cousin[Noun] cove anse[Noun] covenant convention[Noun] cover couvrir[Verb] covert cache/[Adjective] covet covoiter[Adjective] covetous avide[Adjective] covetously avidement[Adjective] cow la moo cowetta[Noun] cow la vache[Noun] coward la^che[Noun] cowardice la^chete/ cowardly la^che[Adjective] cower se blottir[Verb] cowherd vacher[Noun] cowl capuchon[Noun] coxcomb petit-mai^tre[Noun] coy farouche[Adjective] coyly modestement[Adverb] coyness re/serve[Noun] coyote coyote[Noun] cozily confortablement[Adverb] cozy confortable crab cancre[Noun] crabapple pomme sauvage[Noun] crabbed maussade[Adjective] crack fente[Noun] cracker pe/tard[Noun] crackle craqueter[Verb] cradle berceau[Noun] craft fourberie[Noun] craftily astucieusement[Adverb] crag rocher escarpe/[Noun] cram fourrer[Verb] cramp crampe[Noun] cranberry airelle coussinette[Noun] crane grue[Noun] cranium cra^ne[Noun] crank manivelle[Noun] crankiness humeur difficile[Noun] cranky d'humeur difficile[Adjective] crape cre^pe[Noun] crash retentir[Verb] crate caisse a\ claire-voie[Noun] crater crate\re[Noun] crave de/sirer ardemment[Verb] craven poltron[Adjective] crawl ramper[Verb] crayfish e/crevisse[Noun] crayon pastel[Noun] craze manie[Noun] crazily follement[Adverb] crazy fou[Adjective] creak grincer[Verb] cream cr\eme[Noun] creamy cre/meux[Adjective] crease plisser[Verb] create cre/er[Verb] creation cre/ation creator cre/ateur[Noun] creature cre/ature[Noun] credence croyance[Noun] credential certificat[Noun] credit cre/dit[Noun] creditable estimable creditably honourablement[Adverb] creditor cre/ancier[Noun] credo crois[Verb] credulity cre/dulite/[Noun] credulous cr/edule[Adjective] credulously cr/edulement[Adverb] creed credo[Noun] creek crique[Noun] creep ramper[Verb] creeps chair de poule[Noun] cremate incin/erer[Verb] cut couper[Verb] cute mignon, charmant, adorable[Adjective] cute mignonne[Adjective] cuteness gentillesse, charme[Noun] cutoffs limite, seuil[Noun] cutout forme a\ de/couper[Noun] cuts e/conomies, re/duction de budget[Noun] cutter couteau (de de/coupage)[Noun] cutting d/ecoupe, de/coupage[Noun] cyanate cyanante[Noun] cyanide cyanure[Noun] cybernetic cyberne/tique[Adjective] cybernetician cyberne/ticien[Noun] cybernetics cyberne/tique[Noun] cycle cycle[Noun] cyclic cyclique[Adjective] cyclical cyclique[Adjective] cyclist cycliste[Noun] cyclists cyclistes[Noun] cycloid cycloi.de[Noun] cycloidal cycloi.dal[Adjective] cyclone cyclone[Noun] cyclonic cyclonique[Adjective] cyclopean cyclope/en[Adjective] cyclotron cyclotron[Noun] cylinder cylindre[Noun] dad papa[Noun] daddies papas[Noun] daddy papa[Noun] dads papas[Noun] daffy barjot[Adjective] daft barje[Adjective] dagger dague (une)[Noun] dahlia dahlia[Noun] dahlias dahlias[Noun] daily quotidien daintier plus délicat dainty délicat dairy laitier dalmatian dalmatien[Adjective] dalmatians dalmatiens[Noun] dam barrage[Noun] damage abimer[Verb] damage de/ga^t[Noun] damage endommagement damage endommager[Verb] damaged endommage/[Adjective] damaged endommagé[Adjective] damager endommageur damagers endommageurs damages de/ga^ts[Noun] damaging endommageant dame dame dammit merde alors damnation damnation[Noun] damned damne/[Adjective] damp humide[Adjective] dampen humidifier[Verb] dampened humidifie/ dampness humidite/[Noun] dams barrages[Noun] dance danse dancer danceur dancers danceurs dancing danser[Verb] dandelion pissenlit dandelions pissenlits dandies dandys[Noun] dandruff pelicule[Noun] danger danger[Noun] dangerous dangereux[Adjective] d'art d'art day jour[Noun] daybreak aube[Noun] daylight lumiere du jour[Noun] days jours[Noun] deactivate de/sactiver[Verb] deactivation de/sactivation[Noun] dead mort[Adjective] deaf sourd[Adjective] deaths morts deep profond[Adjective] density densite/[Noun] deserve meriter[Verb] d'etat d'état d'etre d'être device pe/riph/erique[Noun] device pe/riphe/rique[Noun] dictated dicté[Verb] dictates dicte[Verb] dictation dictée[Noun] dictations dictées[Noun] dictionaries dictionnaires[Noun] dictionary dictionnaire[Noun] did a fait[Verb] die mourir[Verb] died mort[Verb] diesel diesel[Noun] diet diète[Noun] dietetically diététiquement[Adverb] diets diètes[Noun] different différent[Adjective] difficulties difficultés[Noun] difficulty difficulté[Noun] dig creuser[Verb] digested digéré[Verb] dignitaries dignitaires[Noun] dignities dignités[Noun] dignity dignité[Noun] dilate dilater[Verb] dilated dilaté[Verb] doctor docteur[Noun] document document[Noun] d'oeuvre d'oeuvre dog chien/ne[Noun] doggie chien/ne[Noun] dogs chiens[Noun] drink boire[Verb] drinks boissons[Noun] drive conduire[Verb] driver conducteur[Noun] drizzle bruiner[Verb] dry se/cher[Verb] duck canard[Noun] each chaque eagle aigle[Noun] eagles aigles[Noun] eaglet aiglon[Noun] ear oreille[Noun] earache mal d'oreille[Noun] eardrum tympan[Noun] eardrums tympans[Noun] earlobe lobe d'oreille[Noun] early to^t[Adjective] earn gagner[Verb] earning gagner[Verb] earphones e/couteurs[Noun] earring boucle d'oreille[Noun] earrings boucles d'oreille[Noun] ears oreilles[Noun] earth terre[Noun] earthquake tremblement de terre[Noun] earthquakes tremblements de terre[Noun] earths terres[Noun] earthworm ver de terre[Noun] earthworms vers de terre[Noun] earwax serumen[Noun] ease facilite/[Noun] easel chevalet[Noun] easier plus facile[Adjective] easiest le plus facile[Adjective] easily facilement[Adverb] easiness facilite/[Noun] east est[Noun] easter Pa^ques[Noun] easy facile[Adjective] eat manger[Verb] eatable comestible[Adjective] eats manger[Verb] ebony e/be\ne[Noun] eccentric excentrique[Adjective] eccentricity excentricite/[Noun] ecclesiastic eccle/siastique[Noun] echo e/cho[Noun] eclipse e/clipse[Noun] ecologic e/cologique[Adjective] ecologist e/cologiste[Noun] ecology e/cologie[Noun] economics econom'ica[Noun] ecru e/cru[Adjective] eight huit[Adverb] eighteen dix-huit[Adverb] eighteenth dix-huitie\me[Adjective] eightfold huit fois[Adverb] eighth huitie\me[Adjective] eighties les anne/es quatre-vingt (f)[Noun] eightieth quatre-vingtie\me[Adjective] eighty quatre-vingt[Adverb] eightyfold quatre-vingt fois[Adverb] einsteinium einsteinium (m)[Noun] either soit[Adverb] ejaculate e/jaculer[Verb] ejaculated e/jacule/[Adjective] ejaculates e/jacule[Verb] ejaculating e/jaculant[Adjective] ejaculation e/jaculation (f)[Noun] ejaculations e/jaculations (f)[Noun] ejaculatory e/jaculatoire[Adjective] eject e/jecter[Verb] ejectable e/jectable[Adjective] ejecting e/jectant[Verb] ejection e/jection (f)[Noun] ejector e/jecteur (m)[Noun] ejectors e/jecteurs (m)[Noun] elaborate e/laborer[Verb] elaborated e/labore/ (m), e/labore/e (f)[Adjective] elaborates e/labore[Verb] elaborating e/laborant[Adjective] elaboration e/laboration (f)[Noun] elaborations e/laborations (f)[Noun] elevator ascenseur[Noun] eleven onze[Adjective] eleventh onzie\me[Noun] eliminate e/liminer[Verb] end fin[Noun] environment ambiente[Noun] environmental ambiental[Adjective] envoy enviado[Noun] envy envidia[Noun] envy envidiar[Verb] escalator escalier roulant[Noun] establish constater[Verb] event occasion[Noun] eventual final[Adjective] eventually finallement[Adverb] ever toujours[Adverb] evergreen permanent[Adjective] everlasting permanent[Adjective] every chaque[Pronoun] everywhere partout[Conjunction] eviction mise a` l' e'cart[Noun] evidence preuve[Noun] exclaim s'exclaimer[Verb] fable fable[Noun] fables fables[Noun] fabric tissu[Noun] fabricant fabricant[Noun] fabricate fabriquer[Verb] fabricated fabrique/[Pronoun] fabricates fabrique[Verb] fabricating fabriquant[Verb] fabrication invention(s), fabulation; fait, forge(e) de toutes pieces[Noun] fabrications fabrications[Noun] fabricator fabricant[Noun] fabricators fabricants[Noun] fabrics tissus[Noun] fabulist fabuliste (m)[Noun] fabulous fabuleux(euse); formidable[Adjective] facade fac,ade[Noun] facades fac,ades[Noun] face visage, figure; expression; (of clock) cadran; (of building) facade[Noun] faceless sans face[Noun] faceplate face avant (f),panneau avant (m)[Noun] facet facette[Noun] facetious facétieux[Adjective] facetious plaisant[Adjective] facetiously facétieusement[Adverb] facial facial[Adjective] facies facie\s (m)[Noun] facile facile[Adjective] facilitate faciliter[Verb] facilitated facilite/[Pronoun] facilitates facilite[Verb] facilitating facilitant[Verb] facilities instalations[Noun] facility usine (f), e/tablissement (m)[Noun] facing face a, en face de[Preposition] facsimile (document) telecopie; (machine) telecopieur[Noun] fact fait[Noun] faction faction[Noun] factor facteur[Noun] factorial factoriel factorials factorielles (f)[Noun] factories usines (f)[Noun] factorization factorisation[Noun] factorizations factorisations[Noun] factorize factoriser[Verb] factorized factorisé[Adjective] factors facteurs (m)[Noun] factory usine (m) facts faits[Noun] factual factuel (m),factuelle (f)[Adjective] facultative facultatif[Adjective] facultatively facultativement[Adverb] faculties faculte/s (f)[Noun] faculty faculté fad affaiblir, atte/nuer[Verb] fade se faner[Verb] faded affaibli, atte/nue/[Adjective] fader atte/nuateur (m)[Noun] faders atte/nuateurs (m)[Noun] fading affaiblissement (m), atte/nuation (f)[Noun] faery fe/e[Noun] faience fai.ence fail échouer[Verb] faint s'e/vanouir[Verb] faintly faiblement[Adverb] fair juste[Adjective] fairly e/quitablement[Adverb] fairy fe/e[Noun] faith foi[Noun] faithful fide\le[Adjective] faithfully fide\lement[Adverb] fashion mode[Noun] fashionable a\ la mode[Adjective] fast rapide[Adjective] fasten attacher[Verb] fastener fermeture[Noun] fastidious exigeant[Adjective] fat gros[Adjective] fatal mortel[Adjective] fatalism fatalisme[Noun] fatality victime[Noun] fatally mortellement[Adverb] fate destin[Noun] fish poisson[Noun] fishable pêchable[Adverb] fishbowl bôl à poisson[Noun] fished pêché[Verb] fisher pêcheur[Noun] fisheries poissonneries[Noun] fisherman pêcheur[Noun] fishermen pêcheurs[Noun] fishers pêcheurs[Noun] fishery poissonnerie[Noun] fishes poissons[Noun] fishing à la pêche fishtail queue-de-poisson[Noun] fission fision[Noun] fissionable fisionable[Adverb] fissure fissure[Noun] fist poing[Noun] fisted poingé[Verb] fistful poingée[Noun] five cinq[Adverb] fivefold cinq fois[Adverb] fix re/parer[Verb] fixation fixation (f)[Noun] fixations fixations (f)[Noun] fixity fixite/ (f)[Noun] fixture support (m)[Noun] fixtures supports (m)[Noun] fjord fjord (m)[Noun] fjords fjords (m)[Noun] flight le vol[Noun] floppy disquette[Noun] fluently couramment[Adverb] foot pied[Noun] football football[Noun] forget oublier[Verb] forgetful oublieux[Adjective] forgetfulness manque de me/moire[Noun] forgivable excusable[Adjective] forgivably de fac,on excusable[Adverb] forgive pardonner[Verb] forgiveness pardon[Noun] forgives pardonne[Verb] forgiving indulgent[Adjective] forgo renoncer \a[Verb] forgoes renonce \a[Verb] forgotten oublie/[Adjective] forlorn de/laisse/[Adjective] formaldehyde formalde/hyde four quatre[Adverb] fox renard (m)[Noun] fractal fractale (f)[Noun] fractals fractales (f)[Noun] fraction fraction (f)[Noun] fractionate fractionner[Verb] fraternal fraternel[Adjective] fraternize fraterniser[Verb] friend ami[Noun] friendship Amitie[Noun] fringe frange[Noun] frog grenouille[Noun] frogs grenouilles[Noun] from de front devant[Preposition] fucked foutu[Adjective] fudge sucre a` la cre`me[Noun] fugue fugue[Noun] fulgurant fulgurant[Adjective] funk frouse[Noun] funniest le plus amusant[Adjective] funny amusant[Adjective] gab bavarde[Verb] gabardine gabardine[Noun] gabber comme\re[Noun] gabbing bavarder[Verb] gaberdine une gabardine[Noun] gadget un gadget[Noun] gaiety la gaieté[Noun] gaily gaiement[Adverb] gain le gain[Noun] gained gagne/[Verb] gaining gagnant[Verb] gala un gala[Noun] galactic galactique[Adjective] galaxies galaxies[Noun] galaxy une galaxie[Noun] gallant gallant[Adjective] gallantly gallamment[Adverb] gallantry la gallantrie[Noun] galleries galleries[Noun] gallery gallerie[Noun] gallon un gallon[Noun] gallop galloper[Verb] galloped gallope/[Verb] galloping gallopant[Verb] galvanic galvanique[Adjective] galvanism le galvanisme[Noun] galvanize galvaniser[Verb] galvanized galvanise/[Verb] game un jeu[Noun] games joues[Noun] garlic ail[Noun] gas essence[Noun] gasoline essence[Noun] ghostwriter négre[Noun] gift cadeau[Noun] gifts cadeaux[Noun] go aller[Verb] goal objectif[Noun] goals buts goat oie god dieu goddess de/esse goddesses de/esses godfather parrain[Noun] golf golf golfer geolfeur golfers golfeurs golfs golfs good bon;bien good bien goodbye au revoir goodnight bon nuit gopher gopher[Noun] gospel evangile[Noun] gown la robe grab saisir (an object)[Verb] gradient pente (math.)[Noun] gradually graduellement[Adverb] grammar grammaire (f)[Noun] grape le raisin[Noun] grapefruit le pamplemousse[Noun] habilitated habilite/[Verb] habilitation habilitation[Noun] habit coutume[Noun] habitant habitant[Noun] habitants habitants[Noun] habitat habitat[Noun] habitation demeure[Noun] habitual usuel[Adjective] had se faire avoir hand main[Noun] head tete heats series[Noun] heaven paradis[Noun] heavy lourd[Adjective] hectare hectare hectares hectares hectoliter hectolitre hedge haie hedgehog he/risson[Noun] heed suivre[Verb] heel talon heeler guerisseur heels talons height hauteur heir he/ritier held tenu[Adjective] helices helices[Noun] hell enfer[Noun] hello bonjour[Noun] helm barre[Noun] helmet casque[Noun] help aide[Noun] hemp chanvre[Noun] hen poule[Noun] herd troupeau[Noun] here ic,i[Noun] heron huron[Noun] hips flancs[Noun] hit frapper[Verb] hockey hockey[Noun] hogwash non sense[Noun] holidayer vacancier[Noun] holidays vacances home maison[Noun] homeless sans-abri[Noun] homes maisons[Noun] house maison[Noun] ice glace[Noun] instancing instanciation[Noun] internship stage professionnel en entreprise ou ailleurs jab planter[Verb] jabber baragouiner[Verb] jabberwocky (playing card) valet[Noun] jabberwocky Jaseroque, Bredoulocheux, Berdouilleux, Jabberwocheux[Noun] jack criq[Noun] jack valet[Noun] jackal chacal[Noun] jackals chacaux[Noun] jackass a^ne[Noun] jackdaw choucas (m)[Noun] jacket blouson[Noun] jacket veste[Noun] jackhammer marteau piqueur[Noun] jackknife canif[Noun] jackpot gros lot[Noun] jade jade[Noun] jaded brime/e(e)[Adjective] jag bombe, noce[Noun] jagged e'bre'che[Verb] jail emprisonner[Verb] jail prison jailbreak evasion[Noun] jailed emprisonne/[Adjective] jailer geo^lier[Noun] jailing incarce/ration[Noun] jailor geo^lier[Noun] jails prisons[Noun] jalopy guimbarde[Noun] jam confiture[Noun] jam enfoncer[Verb] jamb jambage[Noun] jammed coince/[Adjective] jammed enraye/[Adjective] jangle (bells) faire retenir[Verb] janitor agent d'entretien[Noun] janitor concierge[Noun] jar bocal[Noun] jar pot[Noun] jar secousse[Noun] jargon jargon (m)[Noun] jasmine jasmin[Noun] jaundice jaunisse[Noun] jaunt balade[Noun] jaunty désinvolte[Adjective] jaunty insouciant(e)[Adjective] javelin javelot[Noun] jaw ma^choir[Noun] jaws ma^choires[Noun] jay geai (m)[Noun] jazz jazz (m)[Noun] jazzy voyant(e)[Adjective] jealous jaloux, jalouse[Adjective] jealousy jalousie[Noun] jeer conspuer[Verb] jeer huer[Verb] jelly gele/e[Noun] jellyfish meduse[Noun] jeopardize compromettre[Verb] jeopardize mettre en danger[Verb] jerk abruti[Noun] jerk bousculer[Verb] jerry boche[Noun] jersey (cloth) jersey[Noun] jersey pull (m)[Noun] jest plaisanterie (f)[Noun] jester bouffon[Noun] jester fou[Noun] jet gicleur[Noun] jet re/acteur[Noun] jettison jeter, larguer[Verb] jetty jete/e[Noun] jewel joyau[Noun] jeweler bijoutier[Noun] jewelery bijouterie[Noun] jewelry bijouterie[Noun] jewels joyaux[Noun] jib (of crane) flèche (f)[Noun] jib (sail) foc (m)[Noun] jiffy (in a ~) en un clin d'oeil jig gigue (f)[Noun] jigsaw (puzzle) puzzle (m)[Noun] jihad lutte, combat (Islam)[Noun] jilt laisser tomber[Verb] jingle (bell) tinter[Verb] jingle (song) jingle (m), indicatif (m)[Noun] jingle (sound) cliquetis (m)[Noun] jinx poisse (f)[Noun] jitters trac[Noun] job boulot (colloq.)[Noun] job emploi (m)[Noun] job turbin (slang)[Noun] jobless au chômage[Adjective] jockey jockey (m)[Noun] jocular enjoué(e), jovial(e)[Adjective] jocund gai[Adjective] jodhpur jodhpur (m)[Noun] jog faire du jogging[Verb] jogging jogging (m)[Noun] join (re)joindre[Verb] join raccord (m)[Noun] joinable joignable[Adverb] joined (re)joint[Adjective] joiner menuisier (m)[Noun] joinery menuiserie (f)[Noun] joint (drugs) joint (m)[Noun] joint articulation[Noun] joint jointure[Noun] jointly conjointement[Adverb] joke blague (colloq.)[Noun] joke plaisanterie[Noun] joked plaisanta (pass.simp.,3rd sing[Verb] joker (playing card) joker (m)[Noun] jokingly en plaisantant[Adverb] jokingly pour rire[Adverb] jolly jovial(e), enjoué(e)[Adjective] jolt secousse[Noun] jolt soubresaut (m)[Noun] jonquils jonquilles[Noun] jostle bousculer[Verb] jot (~ down) noter[Verb] jot (of truth) grain(m), brin(m) journal (diary) journal (m)[Noun] journal (magazine) revue (f) journalism journalisme (m) journalist journaliste[Noun] journalists journalistes[Noun] journey periple[Noun] journey voyage[Noun] jovial jovial(e)[Adjective] jovially jovialement[Adverb] joy joie[Noun] joyful joyeux[Adjective] joyfully joyeusement[Adverb] joyless sans joie[Adverb] joyously joyeusement[Adverb] jubilant débordant(e) de joie[Adjective] jubilee jubilé (m)[Noun] judge juge[Noun] judge juger[Verb] judged juge/[Adjective] judgement jugement[Noun] judicial judiciaire[Adjective] judiciary magistrature (f)[Noun] judo judo (m)[Noun] jug broc[Noun] jug pichet[Noun] jug pot (m)[Noun] juggernaut poids (m) lourd[Noun] juggle jongler[Verb] juggler jongleur (m), jongleusse (f)[Noun] jugular jugulaire[Adjective] juice jus[Noun] juiceless sans jus juicier plus juteux juiciest le plus juteux juicy juteux, juteuse jukebox juke-box (m)[Noun] jumble mélange (m)[Noun] jumbo géant(e)[Adjective] jump sauter (inf.)[Verb] jumped sauta (pass.simp., 3rd sing.)[Verb] jumper robe (f) chasuble[Noun] jumpy nerveux(euse)[Adjective] junction (rail) embranchement (m)[Noun] junction jonction[Noun] jungle jungle (f)[Noun] junior junior juniper genie\vre[Noun] junk bric-à -brac (m)[Noun] junk camelotte (colloq.)[Noun] junk des ordures[Noun] junk du toc (colloq.)[Noun] junkers casseurs (colloq.)[Noun] junkers chiffonniers[Noun] junkie accro (colloq.)[Noun] junkie drogué(e)[Noun] junkyard une casse (automobile)[Noun] juridic juridique[Adjective] jurisdiction juridiction[Noun] jurist juriste[Noun] juror jure/[Noun] jurors jure/s[Noun] jury jury (m)[Noun] just juste justice justice (f)[Noun] justified justifie/(e)[Adjective] justify justifier[Verb] justly justement[Adverb] jut (~ out) avancer[Verb] juvenile puéril(e)[Adjective] juxtapose juxtaposer[Verb] kale chou[Noun] kaleidescope kale/idoscope[Noun] kaleidoscope kale/idoscope[Noun] kangaroo kangourou[Noun] karat carat (m)[Noun] karate karaté (m)[Noun] kayak kayak (m)[Noun] kebab brochette[Noun] keel la quille (naut.)[Noun] keep garder (inf.)[Verb] keeps toujours[Noun] keepsake souvenir (m)[Noun] keg caisson (liq.)[Noun] keg tonnelet (m), baril (m)[Noun] kennel niche (f)[Noun] kennel un chenil[Noun] kerchief un foulard[Noun] kernel amande (f)[Noun] kernel noyau[Noun] kernel trognon (fruit)[Noun] kerosene kérosène (m)[Noun] ketchup ketchup (m)[Noun] kettle une bouilloire[Noun] key (map) légende key une cle/, or clef[Noun] key une touche (keyboard)[Noun] keyboard un clavier[Noun] keyhole le trou de (la) serrure[Noun] keying taper (typewriter) (inf.)[Verb] keynote note (f) dominante[Noun] keypad (keyboard) pavé (m) numérique[Noun] keypad un clavier (adding machine)[Noun] khaki kaki[Adjective] kick (~ out) vider[Verb] kick donner (inf.) un coup de pied[Verb] kickback un retour de manivelle[Noun] kicked frappe/ du pied[Adjective] kicker qui donne des coups de pied[Noun] kickoff le depart synchronise/[Noun] kicks s'amuser kid un chevreau, une chevrette[Noun] kid un(e) gosse (colloq.)[Noun] kid un(e) mioche (colloq.)[Noun] kiddies les gamins[Noun] kiddies les gosses[Noun] kiddies les mioches (colloq.)[Noun] kidnap enlever (inf.)[Verb] kidnap kidnapper[Verb] kidnaped enleve/ (past.part.)[Adjective] kidnaper enlèvement (m)[Noun] kidnaper un ravisseur[Noun] kidnapers les|des ravisseurs[Noun] kidnaping un enle\vement[Noun] kidnapped enleve/[Verb] kidnapper un ravisseur[Noun] kidnappers les|des ravisseurs[Noun] kidnapping un enle\vement[Noun] kidnappings des enle\vements[Noun] kidney le rein[Noun] kidneys les|des reins[Noun] kidneys les rognons (cooking)[Noun] kids les|des gamins[Noun] kids les|des gosses[Noun] kill (fig.) mettre fin à [Verb] kill tuer[Verb] killer meurtrier (m),meutrière (f)[Noun] killer un tueur[Noun] killers des tueurs[Noun] killing meutre (m)[Noun] killing une tuerie[Noun] killings des tueries[Noun] killjoy rabat-joie (m)[Noun] kiln four (m)[Noun] kiln un fourneau[Noun] kilo kilo (m)[Noun] kilobytes kilo-octet (m)[Noun] kilogram kilogramme (abbr. kg)[Noun] kilohertz kilo-hertz (m)[Noun] kiloliter un kilolitre (abbr. kl)[Noun] kilometer un kilome\tre (abbr. km) kilowatt kilowatt (m)[Noun] kilt kilt (m)[Noun] kin aparente/ (a\...)[Adjective] kind aimable[Adjective] kind doux (de caracte\re)[Noun] kind gentil(le)[Adjective] kindergarten (le) jardin d'enfants[Noun] kindergarten (une) cre^che pour enfants[Noun] kindergarten (une) garderie (d'enfants)[Noun] kindergarten e/cole maternelle[Noun] kindhearted bon (de caracte\re, de coeur)[Noun] kindhearted tendre de coeur[Adjective] kindheartedness (la) tendresse de coeur[Noun] kindle (feeling) susciter[Verb] kindle (fire) allumer[Verb] kindlessly froidement[Adverb] kindlessly sans coeur[Adverb] kindliness (la) douceur[Noun] kindliness (la) gentillesse[Noun] kindly avec douceur[Adverb] kindly bienveillant(e)[Adverb] kindly doucement[Adverb] kindly gentiment[Adverb] kindness (la) douceur de coeur[Noun] kindness (la) gentillesse[Noun] kindred aparente/[Adjective] kindred semblable, similaire[Adjective] kinds des espe\ces[Noun] kinds des sortes (de...)[Noun] king (le) roi[Noun] kingdom (animals/plants) règne (m)[Noun] kingdom (le) royaume[Noun] kingdoms royaumes[Noun] kingfisher (un) martin pe^cheur (bird)[Noun] kingly royal[Adjective] kings (les) rois[Noun] kinky vicieux(ieuse)[Adjective] kiosk kiosque[Noun] kipper hereng (m) fumé[Noun] kiss baiser[Verb] kiss baiser[Noun] kiss bisou[Noun] kiss embrasser[Verb] kisses baisers[Noun] kisses bisous[Noun] kit (set) trousse (f)[Noun] kit (to be assembled) kit (m)[Noun] kitchen cuisine[Noun] kitchenette cuisinette[Noun] kitchens cuisines kitchenware (la) batterie de cuisine[Noun] kitchenware (les) ustensiles de cuisine[Noun] kite (un) cerf-volant[Noun] kith (~ and kin) parents et amis kiting jouer avec un cerf-volant[Verb] kitten chaton[Noun] kittens chatons[Noun] kitty (shared fund) cagnotte (f)[Noun] kiwi (bird) kiwi (m), aptéryx[Noun] kiwi (fruit) kiwi (m)[Noun] kleenex (un) mouchoir en papier[Noun] kleenex TM, (R), etc. papier-mouchoir[Noun] kleptomania (la) kleptomanie[Noun] kleptomaniac un(e) kleptomane[Noun] knack _ _ _ _ = avoir la main pour..[Noun] knack to have the _ = avoir le chic[Noun] knapsack (un) sac-a\-dos[Noun] knead pe/trir[Verb] kneadable pe/trissable[Adjective] kneader pe/trisseur[Noun] knee le genou[Noun] kneecap la rotule[Noun] kneel mettre à genoux[Verb] kneel s'agenouiller (inf.reflx.)[Verb] kneeling a\ genoux[Adverb] kneeling s'agenouillant[Verb] kneepad (un) prote\ge-genou[Noun] knelt s'agenouilla (pass.simp.)[Verb] knelt se mis(e) a\ genoux (pass.simp[Verb] knickers pantalon de golf (m)[Noun] knickknack (un) bibelot[Noun] knickknack (une) babiole[Noun] knife (un) canif[Noun] knife (un) couteau[Noun] knifes des couteaux[Noun] knifing une blessure au couteau[Noun] knight (chess) cavalier (m)[Noun] knight (un) chevalier[Noun] knighted e^tre sacre/ chevalier[Adjective] knighthood la chevalerie[Noun] knightly chevalier[Adjective] knights des chevaliers[Noun] knit (bones) se souder[Verb] knit froncer les sourcils[Verb] knit tricotter (inf.)[Verb] knitted tricotte/ (past.part.)[Adjective] knitting le tricot[Noun] knitwear le tricot[Noun] knives des couteaux[Noun] knob (la) poigne/e[Noun] knob (un) bouton (de commande)[Noun] knobby noueux, noueuse[Adjective] knobs (les) boutons (de commande)[Noun] knock frapper (inf.)[Verb] knock tapoter[Verb] knockdown démolir[Verb] knockout knock-out (m)[Noun] knot (un) noeud[Noun] knots des noeuds[Noun] knotted noue/ (past.part.)[Adjective] knotty épineux(euse)[Adjective] knotty noueux[Adjective] know savoir (inf.)[Verb] knower celui|celle qui a le savoir[Noun] knowhow le savoir-faire[Noun] knowhow technique (f)[Noun] knowing entendu(e)[Adjective] knowingly en connaissance de cause[Adverb] knowingly sciemment[Adverb] knowledge la connaissance[Noun] knowledge le savoir[Noun] knowledgeable bien informé(e)[Adjective] known connu (past.part.)[Verb] knows (il|elle) sait[Verb] knuckle (meat) jarret (m) knuckle (une) phalange[Noun] knucklebone (une) phalange[Noun] knuckles (un) poing ame/ricain[Noun] knuckles les phalanges[Noun] koala koala (m)[Noun] kosher cache\re[Adjective] kosher kasher[Adjective] kraut (la) choucroute[Noun] kraut (un) boche (slang)[Noun] krauts les chleus (slang.)[Noun] kudzu lierre du Japon[Noun] lab labo[Noun] labor travail (m)[Noun] laborer l'ouevrier[Noun] laborer l'ouvrier[Noun] laborers les ouevriers[Noun] laborers les ouvriers[Noun] laborious laborieux (m), laborieuse (f)[Noun] labyrinth labyrinthe (m)[Noun] lace dentelle (f)[Noun] laceration lace/ration (f)[Noun] lacerations lace/rations (f)[Noun] lack manque[Noun] lackadaisical nonchalant[Adjective] lackey laquais[Noun] lacking simplet[Adjective] lackluster terne[Adjective] laconic laconique[Adjective] laconically laconiquement[Adjective] lacquer (for wood) vernis (m)[Noun] lacquer laque[Noun] lad garcon[Noun] ladies Mesdames[Noun] lady dame[Noun] ladybird coccinelle[Noun] ladybug coccinelle[Noun] lake lac[Noun] lakes lacs[Noun] lamb veau[Noun] lambs veaux[Noun] laminated laminé[Verb] laminates lamine[Verb] lamp lampe[Noun] language langue[Noun] laugh rire[Verb] leather cuir[Noun] leave laisser[Verb] lectern lutrin[Noun] lecture confe/rence[Noun] lecturer confe/rencier[Noun] ledge rebord[Noun] ledger registre[Noun] lee co^te/[Noun] leg jambe[Noun] legal legal[Adjective] legality legalite[Noun] legalize legaliser[Noun] legally legalement[Adverb] legate leguer[Verb] legation legation[Noun] legend legende[Noun] legendary lengendaire[Adjective] legion legion[Verb] letter additive[] letter ethnic[] letter neighbor[] like aimer[Verb] live vivre[Verb] love aime love amour[Noun] lover amant[Noun] luck chance[Noun] lunch le de/jeuner[Noun] ma maman[Noun] ma Mère[Noun] ma'am M'dame[Noun] ma'am madame[Noun] ma'am mademoiselle[Noun] macabre lugubre[Adjective] macabre macabre[Adjective] macabrely macabrement[Adverb] macadam bitume[Noun] macadam macadam[Noun] macadamize goudronner[Verb] macadamize macadamiser[Verb] macadamized goudronné[Verb] macadamized macadamise/[Adjective] macadamizes goudronnes[Verb] macadamizes macadamise[Verb] macadamizing goudronnant[Verb] macaque macaque[Noun] macaque macaque[Noun] macaroni macaroni[Noun] macaronies macaronis[Noun] macaroon macaron[Noun] macaw l'ara[Noun] mace sceptre[Noun] macerate mace'rer[Verb] macerate maçérer[Verb] macerated macere'[Adjective] maceration mace'ration[Noun] macerations mace'rations[Noun] maces masse[Noun] machete machette[Noun] machination machination[Noun] machine machine[Noun] machined machine/[Adjective] machineries machinerie machinery machinerie[Noun] machines machines[Noun] machinist machiniste[Noun] machinists machinistes[Noun] machismo machisme[Noun] macho macho[Adjective] macrocephalic macroce'phale[Adjective] macrocosm macrocosme[Noun] macroeconomics macroeconomie[Noun] macroevolution macroe'volution[Noun] macroevolutionary macroe'volutionnaire[Adjective] macroinstruction macroinstruction macromolecular macromole'culaire[Adjective] macromolecule macromole'cule[Noun] macromolecules macromole'cules[Noun] macropathological macropathologique[Adjective] macropathology macropathologie[Noun] macrophage macrophage[Noun] macrophages macrophages[Noun] macrophagic macrophage[Adjective] macroprocessor macroprocesseur[Noun] macroscopic macroscopic[Adjective] macrosimulation macrosimulation[Noun] macrostructure macrostructure[Noun] maculate maculer[Verb] maculated macule'[Adjective] maculates macule[Verb] maculation maculation[Noun] maculations maculations[Noun] mad fache'[Adjective] mad fou, folle[Adjective] madam madame[Noun] madams mesdames[Noun] maddened rendu fou[Adjective] made a fait[Verb] made j'adore[Verb] mademoiselle mademoiselle[Noun] mademoiselles mesdemoiselles[Noun] maestro maestro[Noun] mafioso mafieux[Noun] magazine magazine[Noun] magic magique[Adjective] magician magicien[Noun] magicians magiciens[Noun] magistral magistral[Adjective] magistrally magistralement[Adverb] magistrature magistrature[Noun] magma magma[Noun] me moi[Pronoun] mead le hydromel[Noun] meadow le pre/[Noun] meadow pre/[Noun] meadowland les prairies[Noun] meadows pre/s[Noun] meager maigre[Adjective] meagerly maigrement[Adverb] meagre maigre[Adjective] meal repas[Noun] meals repas[Noun] mealtime heure du repas[Noun] mean moyenne[Noun] meander me/andre[Noun] meaningless insense/[Adjective] meanings significations[Noun] means moyen[Noun] meanwhile entretemps[Adverb] measurable mesurable[Adjective] meat viande[Noun] meatball boulette de viande[Noun] meatballs boulettes de viande[Noun] mechanical me/canique[Adjective] mechanician me/canicien[Noun] mechanism me/canisme[Noun] mechanisms me/canismes[Noun] medal me/daille[Noun] medallion me/daillon[Noun] medallions me/daillons[Noun] mediatrice me/diatrice[Noun] mediatrix me/diatrice[Noun] medic me/decin[Noun] medical me/dical[Adjective] medically me/dicalement[Conjunction] medicament me/dicament[Noun] medicaments me/dicaments[Noun] medicinal me/dicinal[Adjective] medicine me/decine[Noun] medicines me/decines[Noun] medico medico[Adjective] medicolegal me/dicole/gal[Adjective] medics me/decins[Noun] medieval me/die/val[Adjective] medievalist me/die/valiste[Noun] medievalists me/die/valistes[Noun] mediocre me/diocre[Adjective] mediocrities me/diocrite/s[Noun] mediocrity me/diocrite/[Noun] meditate me/diter[Verb] meditates me/dite[Verb] meditation me/ditation[Noun] meditations me/ditations[Noun] meditative me/ditatif[Adjective] meditatively d'un air me/ditatif[Adjective] medium me/dium[Noun] medlar ne\fle[Noun] medley me/lange[Noun] medleys me/langes[Noun] medulla me/dulle[Noun] medusae me/duses[Noun] meek doux[Adjective] meekly avec soumission[Adjective] meekness soumission[Noun] meerschaum pipe en e/cume de mer[Noun] megabyte me/ga-octet[Noun] megabytes me/ga-octets[Noun] megacycle me/gacycle[Noun] megahertz me/gahertz[Noun] megalith me/galithe[Noun] megalithic me/galitic[Adjective] megalomania me/galomanie[Noun] megalomaniac me/galomane[Noun] megalomaniacal me/galomane[Adjective] megaphone me/gaphone[Noun] melancholia me/lancolie[Noun] melancholic me/lancolique[Adjective] melange me/lange[Noun] melodic me/lodique[Adjective] melodies me/lodies[Noun] melodious me/lodieux[Adjective] melodrama me/lodrame[Noun] melodramas me/lodrames[Noun] melodramatic me/lodramatique[Adjective] melody me/lodie[Noun] melon melon[Noun] melons melons[Noun] melted fondu[Pronoun] member membre[Noun] members membres[Noun] membrane membrane[Noun] membranes membranes[Noun] membranous membraneux[Adjective] memoir me/moire[Noun] memoirs me/moires[Noun] memorable me/morable[Adjective] memories souvenirs[Noun] memorize me/moriser[Verb] memorized me/morise/[Pronoun] memory me/moire, souvenir[Noun] men hommes[Noun] menace menace[Noun] menaced menace/[Adjective] menagerie me/nagerie[Noun] menageries me/nageries[Noun] menhir menhir[Noun] meningitis me/ningite[Noun] meniscus me/nisque[Noun] menopause me/nopause[Noun] menstrual menstruel[Adjective] menstruation menstruation[Noun] menstruations menstruations[Noun] mental mental[Adjective] mentality mentalite/[Noun] menthol menthol[Noun] mention mentionner[Verb] menu menu[Noun] meow miauler[Verb] meowing miauleur[Adjective] meows miaule[Verb] mephitic me/phitique[Adjective] mercantile mercantile[Adjective] mercantilism mercantilisme[Noun] mercenaries mercenaires[Noun] mercenary mercenaire[Noun] merchant marchand[Noun] merchants marchands[Noun] mercury mercure[Noun] mercy pitie/[Noun] meridian me/ridien[Noun] meridians me/ridiens[Noun] meridional me/ridional[Adjective] merino me/rino[Noun] merit me/rite[Noun] meritocracy me/ritocratie[Noun] merits me/rites[Noun] mermaid sire\ne[Noun] mermaids sire\nes[Noun] merry joyeux[Adjective] message message[Noun] messages messages[Noun] messiahs messie[Noun] messianic messianique[Adjective] moan gémir[Verb] moaned gémit[Verb] moaning gémissant[Verb] moans gémissements moat fossé[Noun] moats fosséa[Noun] mob foule[Noun] mock ridiculiser[Verb] mocked ridiculisé[Verb] mockery moquerie[Noun] modal modal[Adjective] moon lune[Noun] moonlight clair de lune moons lunes moose orignal naive naif, naive[Adjective] naively naivement[Adverb] naked nu[Noun] name prenom(persons), nom (things)[Noun] named nomme[Adjective] nameless sans nom[Adjective] namely nomement [Adverb] namely nommement[Adverb] names prenoms, noms (see name)[Noun] national national/e[Adjective] nationalism nationalisme[Noun] nationalist nationaliste[Adjective] native habitant/e du pays[Noun] natural naturel (le)[Adjective] naturalize naturaliser[Verb] naturally naturellement[Adverb] neap mortes-eaux[Noun] near proche[Adjective] nearby près[Adverb] nearer plus proche[Adjective] neglect abandonner[Verb] neighbor voisin[Noun] neighbors voisins[Noun] network réseau networked réseauté networks réseaux nine neuf[Adjective] nineteen dix-neuf[Adverb] nineteenth dix-neuvie\me[Adjective] nineties les anne/es quatre-vingt-dix[Noun] ninetieth quatre-vingt-dixie\me[Adjective] ninety quatre-vingt-dix[Adverb] ninetyfold quatre-vingt-dix fois[Adverb] ninth neuvie\me[Adjective] niobium niobium (m)[Noun] nip te/ton (m)[Noun] nipple te/ton[Noun] nipples te/tons[Noun] nips te/tons (m)[Noun] nirvana nirvana[Noun] nitrate nitrate[Noun] nitrated nitrate/[Noun] nitrates nitrates[Noun] nitrating nitratant[Adverb] nitration nitratation[Noun] nitrations nitratations[Noun] nitric nitrique[Adjective] nitride nitrate (m)[Noun] nitrogen azote[Noun] nitroglycerin nitroglyce/rine[Noun] nitroglycerine nitroglyce/rine[Noun] noble noble[Noun] nobleman noble[Noun] noblemen nobles[Noun] nobleness noblesse[Noun] nobody personne[Pronoun] noctambulism noctambulisme[Noun] noctambulist noctambule[Noun] nocturn noctune nocturnally de nuit[Noun] now maintenant[Adverb] nowadays de nos jours, aujourd'hui[Adverb] noway pas question, pas du tout[Adverb] noway pas question, pas du tout[Adverb] oaf nigaud[Noun] oafish stupide[Adjective] oafishness sottise[Noun] oak che^ne[Noun] oar rame[Noun] oarsman rameur[Noun] oasis oasis[Noun] oat avoine[Noun] oath serment[Noun] oatmeal farine d'avoine[Noun] obdurate inve/te/re/[Adjective] obedience obe/issance[Noun] obedient soumis[Adjective] obelisk obe/lisque[Noun] obese obe\se[Adjective] obesity obe/site/[Noun] ocean ocean[Noun] one un[Noun] orange orange[Noun] oranges oranges[Noun] orbit orbite[Noun] orbital orbital[Adjective] orbits orbites[Noun] orchestra orchestre[Noun] orchestral orchestral[Adjective] orchestras orchestres[Noun] orchestrated orchestré[Adjective] order commande[Noun] ordered ordonné[Adjective] organism organisme[Noun] organisms organismes[Noun] organist organiste[Noun] organists organistes[Noun] organization organisation[Noun] organizations organisations[Noun] organize organiser[Verb] organized organisé[Adjective] organs organes[Noun] orgasm orgasme[Noun] orgasms orgasmes[Noun] orgies orgies[Noun] orgy orgie[Noun] orient orient[Noun] orientable orientable[Adjective] oriental oriental[Adjective] orientation orientation[Noun] orientations orientations[Noun] oriented orienté[Adjective] orients orients[Noun] orifice orifice[Noun] orifices orifices[Noun] orificial orifique[Adjective] origin origine[Noun] original original[Adjective] originality originalité[Adjective] originally originalement[Adverb] originals originaux[Adjective] origins origines[Noun] ornamental ornemental[Adjective] ornithology ornithologie[Noun] orthodox orthodoxe[Adjective] orthodoxes orthodoxes[Adjective] orthogonal orthogonal[Adjective] pace rhytme[Noun] pace vitesse[Noun] pacemaker stimulateur cardiaque (m), pacemaker (m)[Noun] pachyderm pachyde\rme[Noun] pacific pacifique[Noun] pacifically pacifiquement[Adverb] pacification pacification(f)[Noun] pacifications pacificateur / -trice [Noun] pacificist pacifiste[Noun] pacifier tétine (f), sucette (f) pacifism pacifisme[Noun] pacifist pacifiste[Noun] pacify apaiser[Verb] pacify pacifier[Verb] package 2)paquet(m);3)ballot(m)[Noun] package emballage[Noun] packaged emballeE[Adverb] packaged paquet (m)[Noun] packed (~ with) bourré(e) de packet 1) paquet (m) ;2)ballot(m)[Noun] packing emballage (m)[Noun] pact pacte, contrat[Noun] pacts pcates, contrats[Noun] pad coussinet, tampon[Noun] padding rembourrage, remplissage[Noun] paddle pagaie, palette[Noun] paddock enclos, paddock[Noun] padlock cadenas[Noun] padlock cadenasser[Verb] padrone patron /nne[Noun] paella paella[Noun] pagan pai.en/i.enne) pagan payen /nne[Noun] pagans païen(ne)s[Noun] pageant spectacle[Noun] pageantry apparat[Noun] paid payé(e)[Adjective] pail seau[Noun] pain douleur[Noun] pained peiné(e)[Adjective] painful douleureux[Adjective] painful pénible[Adjective] painfully douloureusement[Adverb] painstaking assidu(e)[Adjective] paint peindre[Verb] paint peinture[Noun] paintbrush pinceau[Noun] painter peintre[Noun] painters peintre[Noun] painting peinture[Noun] paints couleurs[Noun] pair couple[Noun] pajamas pyjama[Noun] pal copain (m)[Noun] pal copine (f) palace palais[Noun] palatable agréable au goût[Adjective] palaver palabres (f)[Noun] pale pâle[Adjective] palette palette (f)[Noun] pall voile (m)[Noun] pallet palette (f)[Noun] pallette palette (f)[Noun] pallor pâleur (f)[Noun] palm (~ tree) palmier (m)[Noun] palm paume (f)[Noun] palpable évident(e)[Adjective] palpable manifeste [Adjective] paltry dérisoire[Adjective] pamper choyer, dorloter[Verb] pamphlet brochure (f)[Noun] pan casserole (f)[Noun] panacea panacée (f)[Noun] panama Panama (m)[Noun] pancake crêpe (f)[Noun] panda panda (m)[Noun] pandemonium tohu-bohu (m)[Noun] pane vitre (f), carreau (m)[Noun] panel invités (m)[Noun] paneling lambris (m)[Noun] panelling lambris (m)[Noun] pang tiraillement (m)[Noun] panic panique (f)[Noun] panic paniquer[Verb] panicky paniqué(e)[Adjective] panorama panorama (m)[Noun] pansy pensée(f)[Noun] pant haleter[Verb] panther panthère (f)[Noun] panties culotte (f)[Noun] pantry garde-manger (m)[Noun] pants pantalon (m)[Noun] papa papa (m)[Noun] paper papier (m)[Noun] paperback livre de poche (m)[Noun] parameter paramètre[Noun] passer passeur[Noun] passion passion[Noun] passionately passionne/ment[Adverb] passive passif[Adjective] passivity passivite/[Noun] password mot de passe[Noun] passwords mots de passe[Noun] past passe/[Noun] pasta pâtes alimentaires[Noun] peat tourbe[Noun] pectorals pectoraux[Noun] peculiar important penitence pe/nitence[Noun] penitences pe/nitences[Noun] penitency pe/nitence[Noun] penitent pe/nitent[Noun] pentadactyl pentadactyle[Adjective] pentadactylism pentadactylisme[Noun] pi pi[Noun] pianist pianiste[Noun] pianistic pianistique[Adjective] piano piano[Noun] picture image[Noun] pictures images[Noun] pie tarte[Noun] pies tartes[Noun] pig cochon[Noun] pigeonhole pigeonnier[Noun] pigment pigment[Noun] pigmentation pigmentation[Noun] pigments pigments[Noun] pigs cochons[Noun] pilot pilote[Noun] pilots pilotes[Noun] pilule pilule[Noun] pine pin[Noun] pineapple ananas[Noun] pineapples ananas[Noun] pines pins[Noun] pink rose[Noun] pocket poche[Noun] pocketbook livre de poche[Noun] pocketbooks livres de poche[Noun] pockets poches[Noun] podium podium[Noun] pogrom pogrom[Noun] pogroms pogroms[Noun] pointer pointeur[Noun] pointers pointeurs[Noun] pointillism pointillisme[Noun] pointillist pointilliste[Noun] pointilliste pointilliste[Noun] pointillistic pointilliste[Noun] poison poison[Noun] poisonous poison[Adjective] poisonousness toxicite/[Noun] poisons poisons[Noun] polar polaire[Adjective] polarities polarite/s[Noun] polarity polarity[Noun] polarize polariser[Verb] polarized polarise/[Adjective] polemical pole/mique[Adjective] polemically de fac,on pole/mique[Adjective] polemically de manie\re pole/mique[Adverb] polemicize pole/miquer police police[Noun] policeman agent de police[Noun] policeman agent[Noun] policeman policier[Noun] policemen agents de police[Noun] policemen agents[Noun] policemen policiers[Noun] policewoman contractuelle[Noun] policewomen contractuelles[Noun] policy politique[Noun] polish polonais[Adjective] polish Polonais[Noun] polite poli[Adjective] politely poliment[Adverb] politeness politesse[Noun] political politique[Adjective] politically politiquement[Adverb] politician politicien[Noun] politicians politiciens[Noun] politics politique[Noun] polka polka[Noun] pollutant polluant[Noun] pollute polluer[Verb] polluted pollue/[Adjective] polluter pollueur[Noun] pollution pollution[Noun] polonium polonium[Noun] poltergeist poltergeist[Noun] polyandrous polyandre[Adjective] polyandry polyandrie[Noun] pour french[Noun] pout moue[Noun] poverty pauvrete/[Noun] powder poudre[Noun] powdery poudreux[Adjective] power puissance[Noun] powerful puissant[Adjective] powerless impuissant[Adjective] powwow assemble/e[Noun] practicability possibilite/[Noun] practicable re/alisable[Adjective] practical pratique[Adjective] pray prier[Verb] prayer prie\re[Noun] prayers prie\res[Noun] praying en prie\res[Adjective] praying prie\re[Noun] preach pre^cher[Verb] preach prononcer[Verb] preacher pasteur[Noun] preacher pre/dicateur[Noun] preachers pasteurs[Noun] preachers pre/dicateurs[Noun] preaches pre^che[Verb] preaches prononce[Verb] preachify faire la morale[Verb] preaching pre/dication[Noun] preaching pre^cheur[Adjective] preaching sermons[Noun] preachy pre^cheur[Adjective] preachy sermonneur[Adjective] preamplifier pre/amplificateur[Noun] preamplifiers pre/amplificateurs[Noun] prearrange arranger au pre/alable[Verb] prearrange arranger d'avance[Verb] prince prince[Noun] princedom principaute/ princely princier[Adjective] princes princes[Verb] princess princesse[Noun] principal principal[Noun] principal directeur[Noun] principalities principaute/s[Noun] principality principaute/ principally principalement principally surtout principals directeurs principle principe[Noun] principles principes print empreinte[Noun] print impression[Noun] print marque printable imprimable[Adjective] printed imprime/[Adjective] printer imprimeur[Noun] printer imprimante[Noun] priorities priorite/ priorities priorite/s priority priorite/ prove prouver[Verb] pulse impulsion[Noun] pulverizable pulverisable[Adjective] pulverizables pulverisables[Adjective] pulverization pulverisation[Noun] pulverize pulveriser[Verb] pulverized pulvérisé[Verb] pulverizer pulverisateur[Noun] pulverizers pulvérisateurs[Noun] pulverizes pulvérises[Verb] pulverizing pulve/risant[Verb] puma puma[Noun] pump pomper[Verb] push pousser[Verb] pushchair chaise roulante[Noun] pushing poussé[Verb] put mettre[Verb] putdown poser[Verb] putout éteindre[Verb] putrefaction putréfaction[Noun] quail caille[Noun] quails cailles[Noun] quake trembler[Verb] quality qualite/[Noun] qualm scrupule[Noun] qualms scrupules[Noun] quantity quantite/ quarrel se disputer[Verb] quarry carri\ere[Noun] quarter quartier[Noun] quarterdeck plage arri\ere[Noun] quarterfinal quart de finale[Noun] queen reine[Noun] queer bizarre[Adjective] quell re/primer[Verb] quench se de/salte/rer querulous ronchonneur[Adjective] query question[Noun] quest que^te[Noun] question question[Noun] queue queue[Noun] quibble chicaner[Verb] quick rapide[Adjective] quicklime chaux vive[Noun] quickly rapidement[Adverb] quicksand sables mouvants[Noun] quicksilver vif-argent[Noun] quiet tranquille[Adjective] quieten calmer[Verb] quietly doucement[Adverb] quill plume d'oie[Noun] quilt e/dredon[Noun] quirk bizarrerie[Noun] quit se rendre[Verb] quite assez[Adjective] quota quota[Noun] quotation citation[Noun] quote citer[Verb] r r[Noun] rabbet feuillure[Noun] rabbi rabbin rabbinic rabbinique[Adjective] rabbit lapin[Noun] rabbits lapins[Noun] rabble cohue[Noun] rabid enrage/[Adjective] rabies rage raccoon raton-laveur race course[Noun] racehorse cheval de course racemic rece/mique[Adjective] racer coureur races courses[Noun] rachis rachis[Noun] rachitic rachitique[Adjective] rachitis rachitisme[Noun] racial racial[Adjective] racialism racisme[Noun] racialist raciste[Noun] racialistic raciste[Adjective] racing de course racism racisme[Noun] racist raciste[Noun] rack e/tag\ere[Noun] racket raquette[Noun] racket tumulte[Noun] radar radar[Noun] radars radars[Noun] radio radio[Noun] read lire[Verb] readability lisibilite/[Noun] readable lisible[Adjective] reader lecteur[Noun] readers lecteurs[Noun] readership lecteurs[Noun] readership lectorat[Noun] readily de bonne gra^ce[Adverb] readily facilement[Adverb] readily volontiers[Adverb] readiness empressement[Noun] readiness facilite/[Noun] reading interpre/tation[Noun] reading lecture[Noun] reading releve/[Noun] readings interpre/tations[Noun] readings lectures[Noun] readjust rajuster[Verb] readjust re/ajuster[Verb] readjusts rajuste[Verb] readjusts re/ajuste[Verb] readout affichage[Noun] readout d'affichage[Adjective] readouts affichages[Noun] reads lit[Verb] ready dispose/[Adjective] ready pre^t[Adjective] ready prompt[Adjective] reaffirm affirmer de nouveau[Verb] reaffirm re/affirmer[Verb] reaffirms affirme de nouveau[Verb] reaffirms re/affirme[Verb] reagent re/actif[Noun] real naturel[Adjective] real ve/ritable[Adjective] real vrai[Adjective] realisable re/alisable[Adjective] realism re/alisme[Noun] realist re/aliste[Noun] realistic plein de re/alisme[Adjective] realistic re/aliste[Adjective] realistically avec re/alisme[Adverb] reality re/alite/[Noun] realize re/aliser[Verb] really vraiment[Adverb] reporter le reporter[Noun] represent repre/senter[Verb] request demande[Noun] request exiger[Verb] request reque^te[Noun] road rue[Noun] roads rues roadwork chantier[Noun] robber voleur[Noun] room chambre rotting decay[Verb] sabbat un sabbat[Noun] sabbath sabbat[Noun] sabbatic sabatique[Noun] sabbatical sabbatique[Adjective] saber sabre[Noun] sabin nom de personne qui a decouvert le vaccine contre poliomyltie[Noun] sable martre[Noun] sabot sabot[Noun] sabotage sabotage[Noun] sabotaged saboté[Verb] sabotages sabotages[Noun] saboteur saboteur[Noun] sabra citoyen du pays Israel, personne ne en Israel[Noun] sabras citoyens du pays Israel, personnese nes en Israel[Noun] saccade une saccade[Noun] saccharin saccharine[Verb] saccharine saccharin[Noun] saccharose saccharose[Noun] sacerdotal appartient a une chose religieuse[Adjective] sacerdotally une acte faite en manière sacrée[Adverb] sachet un sachet[Noun] sack sac[Noun] sack virer[Verb] sackcloth une vêtement de deuil[Noun] sacked vire/[Adjective] sackful une mesure "plein d'un sac"[Adjective] sacks piller[Verb] sacrament sacrament[Noun] sacramental sacremental[Adjective] sacraments sacrements[Noun] sacre sacre[Noun] sacred sacre/[Adjective] sacrifice sacrifice[Noun] sacrificed sacrifier[Verb] sacrifices sacrifices[Noun] sacrilege sacrile\ge[Noun] sad malheureux[Adjective] sad triste[Adjective] sadden attrister[Verb] sadder plus triste[Adjective] saddest plus triste[Adjective] saddle selle[Noun] saddlebag une sacoche[Noun] saddlebags des sacoches saddlebow un arçon saddlecloth une housse ( de cheval)[Noun] saddled sellé[Verb] saddleless sans selle saddler un sellier[Noun] saddlery une sellerie[Noun] saddles une selle saddletree un bois de selle[Noun] saddling sellant[Verb] sadism sadisme[Noun] sadist sadiste[Noun] sadistic sadique[Adjective] sadistically sadiquement[Adverb] sadists sadistes[Noun] sadly tristement[Adverb] sadness tristesse[Noun] safari un voyage, en particulier en Afrique[Noun] safe coffre-fort[Noun] safecracker une personne qui ouvre une caisse illégalement[Noun] safecracking l'acte d'ouvrir une caise illégalement[Noun] safeguard une sauvegarde[Noun] safeguarded sauvegardé[Verb] safeguards garde fous[Noun] safer pplus sauf[Adjective] safes les caisses[Noun] safest le plus sauf[Adjective] safety le sûreté[Noun] safflower le carthame[Noun] saffron le safran[Noun] sag plier, ployer[Verb] saga une saga[Noun] sagacious prudent[Adjective] sagaciously prudemment[Adverb] sagaciousness la sagacité[Noun] sagacity la sagacité[Noun] sage le sage[Noun] sagely sagement[Adjective] sago le sagou[Noun] saguaro une type de cactus[Noun] sahib une forme d'addresser pour un homme des Indes[Noun] said dit[Verb] sail naviguer[Verb] sail voile[Noun] sailable navigable[Adjective] sailboat un bateau à voiles[Noun] sailboater un marin des bateua à voiles[Noun] sailcloth la toile à voiles[Noun] sailor marin[Noun] sailors les marins[Noun] sails les voiles[Noun] sainfoin le sainfoin ( bot.)[Noun] saint saint(e)[Noun] sainted sacré[Adjective] sainthood la sainteté[Noun] saints saint(e)s[Noun] saith dit ( vieux anglais)[Verb] sake le vin du riz japonais[Noun] salability vendabilite/[Adjective] salacious grivois[Adjective] salad salade[Noun] salads salades[Noun] salamander salamandre[Noun] salami salami[Noun] salaried salarie/[Adjective] salaries salaires[Noun] sale solde[Noun] saleable vendable[Adjective] saleroom la salle des ventes[Noun] sales les ventes[Noun] salesclerk un vendeur salesgirl une vendeuse[Noun] saleslady une vendeuse[Noun] salesman un vendeur[Noun] salesmanship l'art de vendre[Noun] salesmen les vendeurs[Noun] salespeople les vendeurs[Noun] salesperson un vendeur[Noun] salesroom les salles de ventes[Noun] saleswoman une vendeuse saleswomen les vendeuses[Noun] salient saillant[Adjective] saline salin[Adjective] salinity la salinité[Noun] salinometer un salinomère[Noun] salinometers des salinomètres[Noun] saliva salive[Noun] salivary salivaire[Adjective] salivate saliver[Verb] salivated a fait saliver[Verb] salivates fait saliver[Verb] salivating faisant saliver[Verb] salivation ;a salivation[Noun] sallies les sorties[Noun] sallow jaunâtre[Adjective] sallowish un peu jaunâtre[Adjective] salmon saumon[Noun] salmons saumons[Noun] salon salon[Noun] salons salons[Noun] salt sel[Noun] saltwater l'eau de mer[Noun] saltworks la saline[Noun] saltwort le soude ( bot.)[Noun] salty sale/[Adjective] salubrious salubre[Adjective] salubrity la salubrité[Noun] salvage le sauvetage[Noun] salver le plateau[Noun] samba la Samba, une danse originée du Brasil[Noun] same même[Adjective] sampan un bateua chinois[Noun] samphire le passe-pierre (bot.)[Noun] samurai un guerrier ancien japonais[Noun] samurais des guerriers anciens japonais[Noun] sand le sable[Noun] sandal la sandale[Noun] school e/cole[Noun] sea mer[Noun] sell vendre[Verb] seller le vendeur[Noun] sellers les vendeurs[Noun] serendipity le serendiptiy[Verb] serene le serene seven sept[Adverb] sevenfold sept fois[Adverb] seventeen dix-sept[Adverb] seventeenth dix-septie\me[Adjective] seventh septie\me[Adjective] seventies les anne/es soixante-dix[Noun] seventieth soixante-dixie\me[Adjective] seventy soixante-dix[Adverb] seventyfold soixante-dix fois[Adverb] sever blesser[Verb] severalfold plusieurs fois[Adverb] severe grave[Adjective] severed blesse/ (m), blesse/e (f)[Adjective] severely gravement[Adverb] severities blessures (f)[Noun] severity gravite/ (f)[Noun] sewage e/pandage (m)[Noun] sex sexe (m)[Noun] sexagenarian se/xage/naire[Adjective] shades lunettes de soleil (f)[Noun] shadow ombre (f)[Noun] shadows ombres[Noun] shagreen chagrin[Noun] shah schah[Noun] shake secouer[Verb] shakedown lit de fortune[Noun] shaken secoue/[Adjective] shaky tremblant[Adjective] shaman chaman[Noun] shamanism chamanisme[Noun] shampoo shampooing shampoos shampooings sheep agnis[Noun] sheepherder pastor[Noun] ship ba^teau ship navire[Noun] shit merde[Noun] sick malade[Adverb] silver argent[Adjective] sing chanter[Verb] singer chanteur[Noun] sink couler[Verb] six six[Adverb] sixteen seize[Adverb] sixteenth seizie\me[Adjective] sixties les anne/es soixante (f)[Noun] sixty soixante[Adverb] sixtyfold soixante fois[Adverb] size taille (f), dimension (f)[Noun] skate patin (m)[Noun] skateboard planche a\ roulettes (f)[Noun] skateboarder planchiste (m)[Noun] skateboarding faire de la planche a\ roulettes[Verb] skateboards planches a\ roulettes (f)[Noun] skater patineur (m), patineuse (f)[Noun] skaters patineurs (m), patineuses (f)[Noun] skates patins (m)[Noun] skating patinage (m)[Noun] skill Habilete/[Noun] skilled habile[Adjective] skilless maladroit[Adjective] skillful adroit[Adjective] skills talents[Noun] sky ciel[Noun] skylark rossignol[Noun] skyscraper gratte-ciel[Noun] snout groin[Noun] snow neige[Noun] snowball boule de neige[Noun] snowflake flocon de neige snowman bonhomme de neige[Noun] snowstorm tempe^te de neige[Noun] software logiciel[Noun] sorrel oseille[Noun] sorrily tristement[Adverb] sorrow tristesse[Noun] sort trier[Verb] sorted trié[Adjective] sorter trieur[Noun] soul âme[Noun] spectra pl de spectrum, spectre[Noun] spectrum Phys: spectre; Fig: gamme (de produit)[Noun] speculate s'interroger, speculer, conjecturer[Verb] speculation meditation; conjectures ; speculation staple agrafe[Noun] stapled agraf/e[Adjective] stapler agrafeuse[Noun] staplers agrafeuses[Noun] staples agrafes[Noun] star e/toile[Noun] stars e/toiles[Noun] start de/part[Noun] stifled e/touffe/ strength force[Noun] stupid Stupide[Adjective] subject asignatura[Noun] succeed re/ussir[Verb] success re/ussite/[Noun] sun soleil[Noun] sunbathe se bronzer[Verb] sunny ensoleille/[Adjective] suppressed e/touffe/ suspect soupc,onner[Verb] swear jurer ; preter serment[Verb] tab happy[Adjective] tab sortir[Verb] tabernacle tabernacle[Noun] table table[Noun] tableau tableau[Noun] tableaus tableaux[Noun] tableaux tableaux[Noun] tablecloth nappe[Noun] tablecloths nappes[Noun] tables tables[Noun] tablet comprime/[Noun] tablets comprime/s[Noun] taboo tabou[Noun] taboos tabous[Noun] tachometer tachyme\tre[Noun] tachometers tachyme\tres[Noun] tacit tacite[Adjective] tail queue (of animal)[Noun] tailor tailleur[Noun] tailored fait sur mesure[Adjective] tailors tailleurs[Noun] tails queues[Noun] task tâche[Noun] tasks tâches[Noun] taste goût[Noun] tasted goûté[Verb] tasteless insipide[Adjective] tear accroc[Noun] tear de/chirer[Verb] tear de/chirure[Noun] tear larme[Noun] teardrop larme[Noun] tearful tout en pleurs[Adjective] tearfully en pleurant[Adverb] tearfully les larmes aux yeux[Adverb] teargas gaz lacrymoge\ne[Noun] tearjerker me/lo[Noun] tearless avec yeux secs[Adjective] tearless sans larmes[Adjective] tearoom salon de the/[Noun] tears de/chirures[Noun] tears larmes[Noun] tearstained barbouille/ de larmes[Adjective] tearstained portant des traces de larmes[Adjective] tease taquin[Noun] tease taquiner[Verb] tease tourmenter[Verb] teasel carde\re[Noun] teaser question dificile[Noun] teaser taquin[Noun] teases excite[Verb] teases taquine[Verb] teases taquins[Noun] teasing railleur[Adjective] teasing taquinerie[Noun] teasingly d'un ton railleur[Adverb] teasingly pour taquiner[Verb] teaspoon cuille\re a\ cafe/[Noun] teaspoon cuiller a\ cafe/[Noun] teaspoonful cuillere/e a\ cafe/[Noun] teat bout de sein[Noun] teat mamelon[Noun] teat tette[Noun] teat trayon[Noun] teatime l'heure du the/[Noun] teats mamelons[Noun] teats tettes[Noun] ten dix[Adverb] tendencies tendances (f)[Noun] tendency tendance (f)[Noun] tenderfoot visage pa^le (m)[Noun] tenderly tendrement[Adverb] thence de la\[Adverb] thence pour cette raison[Adverb] thenceforth de\s lors[Adverb] thenceforward de\s lors[Adverb] theocracy the/ocratie[Noun] theocratic the/ocratique[Adjective] theodolite the/odolite[Noun] theologian the/ologien[Noun] theologians the/ologiens theological the/ologique[Adjective] theologically the/ologiquement[Adverb] theology the/ologie[Noun] theorem the/ore\me[Noun] theorems the/ore\mes[Noun] theoretical the/ore/tique[Adjective] theoretical the/orique[Adjective] theoretically the/oriquement[Adverb] theoretician the/oricien[Noun] theoretician the/oricienne[Noun] theoreticians the/oriciennes[Noun] theoreticians the/oriciens[Noun] theories the/ories[Noun] theorist the/oricien[Noun] theorist the/oricienne[Noun] theorists the/oriciennes[Noun] theorists the/oriciens[Noun] theorize the/oriser[Verb] thief voleur[Noun] though cependant, pourtant[Adverb] though quoique , bien que[Conjunction] thought pensee,idee[Noun] thought reflexion; intention, dessein[Noun] thoughtful pensif, meditatif, reveur[Adjective] thoughtful serieux, reflechi, prudent[Adjective] thoughtfully pensivement[Adverb] thoughtfulness meditation, recueillement[Adjective] thoughtless irreflechi, etourdi[Adjective] thoughtlessly etourdiment, a la legere, sans reflexion[Adverb] thoughtlessness irreflexon, etourderie[Noun] thousand mille, millier[Noun] thousandth millieme[Noun] thrash ecraser qn, rouer qn de coup, [Verb] thrash se debattre, se demener[Verb] thread enfiler (une aiguille); se faufiler ; fileter[Verb] thread filament, fil de soie[Noun] thread Filet, pas de vis [Noun] threadbare elime, rape, use[Adjective] threat menace[Noun] threaten menacer[Verb] threatening menacant[Adjective] threateningly d'un ton menacant[Adverb] three trois[Article] tigress tiger[Noun] today au'jour d'hui[Noun] toe doigt a pied[Noun] tradition tradition[Noun] traditional traditional[Adjective] trail piste[Noun] train train[Noun] trainee stagiare[Noun] trainer encadreur[Noun] traitor trai^tre[Noun] transaction transaction[Noun] transalpine transalpin[Adjective] transcribe transcrire[Verb] transfer transfert[Noun] translate traduire[Verb] translation traduction[Noun] translator traducteur[Noun] transmit transmettre[Verb] tree arbre[Noun] truck camion two deux[Article] ubiquitous omnipre/sent[Adjective] ubiquity ubiquite/[Noun] udder pis[Noun] ugh pouah uglier plus laid[Adjective] ugliest le plus laid[Adjective] uglify enlaidir[Verb] uglily laidement ugliness laideur[Noun] ugly laid[Adjective] ukulele guitare hawai.enne[Noun] ulcer ulce\re[Noun] ulcerate ulce/rer[Verb] ulcerated ulce/reux[Adjective] ulceration ulce/ration[Noun] ulcerative ulce/ratif[Adjective] ulna cubitus[Noun] ultimo du mois dernier[Adverb] unemployment chomage[Noun] vacant (room, seat) libre; (stare) vague; (post) vacant[Adjective] vacate quitter[Verb] vacation vacances[Noun] vaccinate vacciner[Verb] vaccinated vacciner vacuum vide; (vacuum cleaner) aspirateur [masc] [Noun] vacuumed passer a\ l'aspirateur[Verb] vagina vagin (masc.)[Noun] vagrant vagabond(e) [m(f)][Noun] vague vague; (outline, photograph) flou; (absent minded) distrait[Adjective] vain (hope) vain; (promise) vide; (conceited) vaniteux, [f] -euse [Adjective] wacky drole[Adjective] wag remuer[Verb] walnut la noix[Noun] warehouse entrepot warehouse entrepôt[Noun] warehouses entrepôts[Noun] wash laver[Verb] weep pleurer[Verb] weeping pleurs[Noun] weeping qui pleure[Adjective] weeps pleure[Verb] weepy larmoyant[Adjective] weepy me/lo[Noun] weevil charanc,on[Noun] weft trame[Noun] weigh mesurer[Verb] weigh peser[Verb] weighing pese/e[Noun] weighings pese/es[Noun] weighs pe\se[Verb] weight poids[Noun] weighted leste/[Adjective] weighted ponde/re/[Adjective] weightily avec force[Adverb] weightily puissamment[Adverb] weighting lestage[Noun] weighting plombage[Noun] weightless e/tat d'apesanteur[Adjective] weightlessness apesanteur[Noun] weights attache un poids a\[Verb] weights se/rie de poids[Noun] weighty lourd[Adjective] weighty pesant[Adjective] weir barrage[Noun] weird bizarre[Adjective] weird e/trange[Adjective] weirdie excentrique[Noun] weirdies excentriques[Noun] weirdly e/trangement[Adverb] weirdness caracte\re e/trange[Noun] weirdness e/trangete/ inquie/tante[Noun] weirdo excentrique[Noun] weirdos excentriques[Noun] weirs barrages[Noun] welcome agre/able[Adjective] welcome bienvenu[Adjective] welcome bienvenue[Noun] welcome souhaiter la bienvenue a\[Verb] where ou\[Adjective] window la fene^tre[Noun] window le guichet [tickets, etc.] windowpane la glace[Noun] windowpanes les glaces windows les fene^tres windshield le parebrise[Noun] windstorm la tempe^te[Noun] windup remonter[Verb] wine le vin[Noun] wineglass le verre de vin[Noun] winegrower le vigneron[Noun] winemaker l'encaveur (m)[Noun] winemaking la vinification[Noun] winepress le pressoir[Noun] wines les vins[Noun] winey vineux (-se)[Adjective] wing l'aile (f)[Noun] winglet l'aileron (m)[Noun] wink un clin d'oeil[Noun] winter l'hiver (m) wipe essuyer wire fil me/tallique, fil de fer[Noun] wire telegramme[Noun] wire telegraphier ; faire l'installation electrique[Verb] wired branche , sonorise[Adjective] wireless sans fil[Adjective] wiring installation electrique[Noun] wiry raide, rude ; maigre et nerveux wisdom sagesse[Noun] wise sage, prudent, savant[Adjective] wisecrack astuce, sarcasme[Noun] wisely sagement, prudement[Adverb] wiser plus sage[Adjective] wish desir, souhait[Noun] wish desirer, souhaiter qch[Verb] wishbone brechet[Noun] wishes pl de wish, desir[Noun] wishful that's wishfull thinking (on your part ): tu te fais des illusions[Adjective] witch sorcie\re[Noun] witches sorcie\res[Noun] with avec[Conjunction] withdraw retirer[Verb] withdraw se retirer [intr] without sans witness te/moigner[Verb] witness te/moin[Noun] witnesses te/moins[Noun] wolverine le carcajou[Noun] wolverine le glouton[Noun] world le monde[Noun] worldwide mondial[Adjective] xenophobe xe/nophobe[Noun] xenophobia xénophobie[Noun] xenophobic xe/nophobe[Adjective] xerographic xe/rographique[Adjective] xylem xyle\me[Noun] xylene xyle\ne[Noun] xylophone xylophone[Noun] xylophones xylophone[Noun] xylophonist joueur (joueuse) de xylophone[Noun] xylose xylose[Noun] xylotomic xylotomique[Adjective] yacht yacht[Noun] yachting yachting[Noun] yachtsman yachtsman yak yack[Noun] yam patate douce[Noun] yank tirer d'un coup sec[Verb] yap japper[Verb] yard yard (3 ft)[Noun] yardstick mesure[Noun] yarn fil[Noun] yawn bâillement[Noun] yawn bâiller[Verb] yawning ba^illement[Noun] yeah ouais! year année[Noun] yearbook annuaire[Noun] yearlong annuel[Noun] yearly annuel(le)[Adjective] yearly annuellement[Adverb] yearn désirer[Verb] yearning de/sir[Noun] yearningly de/sireux[Adjective] years années[Noun] yeast levure[Noun] yell hurlement[Noun] yell hurler[Verb] yellow jaune[Adjective] yellowed jauni[Adjective] yellowing jaunissant[Adjective] yellowish jauna^tre[Adjective] yes oui yesterday hier[Noun] yet encore[Adverb] yew if[Noun] yield produire[Verb] yoga yoga[Noun] yoghurt yaourt[Noun] yogurt yaourt[Noun] yoke joug[Noun] yolk jaune d'oeuf[Noun] you (formal and/or plural) vous[Pronoun] you (informal and singular) tu[Pronoun] young jeune[Adjective] younger plus jeune[Adjective] youngster jeune[Noun] youth jeunesse[Adjective] youthful juvénile[Adjective] yuppie yuppie[Noun] zabaglione sabayon[Noun] zany dingue[Adjective] zazen zazen[Noun] zeal zèle[Noun] zealous zélé(e)[Adjective] zebra zèbre[Noun] zenith zénith[Noun] zero zero[Noun] zero zéro zest piquant[Noun] zigzag zigzaguer[Verb] zinc zinc[Noun] zipper fermeture[Noun] zodiac zodiaque[Noun] zodiac zondiaque[Noun] zone zone[Noun] zone zone[Noun] zoo zoo[Noun] zoology zoologie[Noun] zoom aller en trombe[Verb] zucchini courgette[Noun] |
Added tests/store-load.tcl.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | #!/usr/bin/env tclsh lappend auto_path . package require Thread if {[llength $argv] != 3} { puts "Usage: $argv0 handle path times" puts { handle A persistent storage handle (see [tsv::array bind] manpage). path The path to file containing lines in the form of "key<tab>val", where key is a single-word and val is everyting else. times The number of times to reload the data from persistent storage. This script reads lines of data from <path> and stores them into the persistent storage described by <handle>. Values for duplicate keys are handled as a lists. The persistent storage engine is then stress-tested by reloading the whole store <times> times. } exit 1 } lassign $argv handle path times ### Cleanup set filename [string range $handle [string first : $handle]+1 end] file delete -force $filename ### Load and store tab-separated values tsv::array bind a $handle set fd [open $path r] set start [clock milliseconds] set pairs 0 while {[gets $fd line] > 0} { if {[string index $line 0] eq {#}} { continue } set tab [string first { } $line] if {$tab == -1} { continue } set k [string range $line 0 $tab-1] set v [string range $line $tab+1 end] if {![tsv::exists a $k]} { incr pairs } tsv::lappend a $k $v } puts "Stored $pairs pairs in [expr {[clock milliseconds]-$start}] milliseconds" tsv::array unbind a tsv::unset a ### Reload set pairs 0 set iter [time { tsv::array bind a $handle set pairs [tsv::array size a] tsv::array unbind a tsv::unset a } $times] puts "Loaded $pairs pairs $times times at $iter" ## Dump file stats puts "File $filename is [file size $filename] bytes long" |
Changes to tests/thread.test.
︙ | ︙ | |||
142 143 144 145 146 147 148 149 150 151 152 153 154 155 | test thread-7.0 {thread::exit} { ThreadReap set tid [thread::create -joinable {thread::exit}] set c [thread::join $tid] ThreadReap set c } {666} test thread-8.0 {thread::exists - true} { ThreadReap set c [thread::exists [thread::create]] ThreadReap set c } {1} | > > > > > > > > > > > > > > > > > > > > | 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | test thread-7.0 {thread::exit} { ThreadReap set tid [thread::create -joinable {thread::exit}] set c [thread::join $tid] ThreadReap set c } {666} test thread-7.1 {thread::exit - # args} { set tid [thread::create] catch {thread::send $tid {thread::exit 1 0}} msg set msg } {wrong # args: should be "thread::exit ?status?"} test thread-7.2 {thread::exit - args} { set tid [thread::create] catch {thread::send $tid {thread::exit foo}} msg set msg } {expected integer but got "foo"} test thread-7.3 {thread::exit - status} { ThreadReap set tid [thread::create -joinable {thread::exit 0}] set c [thread::join $tid] ThreadReap set c } {0} test thread-8.0 {thread::exists - true} { ThreadReap set c [thread::exists [thread::create]] ThreadReap set c } {1} |
︙ | ︙ |
Added tests/tkt-84be1b5a73.test.
> > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package require tcltest namespace import ::tcltest::* tcltest::loadTestedCommands package require Thread # This test used to segfault before commit f4c95731c0. test tkt-84be1b5a73 {Ticket 84be1b5a73} -body { set t [thread::create] set resultvar() {} trace add variable resultvar() write { unset -nocomplain resultvar() list} proc errorproc {tid einfo} {} thread::errorproc errorproc thread::send -async $t { error "" } resultvar() after 1000 { set forever 1 } vwait forever } -returnCodes 0 |
Changes to tests/tsv.test.
|
| > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | package require tcltest namespace import ::tcltest::* tcltest::loadTestedCommands package require Thread set backends {gdbm lmdb} foreach b $backends { testConstraint have_$b [expr {$b in [tsv::handlers]}] } foreach backend $backends { set db "data" file delete -force $db set ::handle $backend:$db proc setup {} { tsv::array bind a $::handle } proc cleanup {} { tsv::array unbind a } test tsv-$backend-1.0 {tsv::array isboud} \ -constraints have_$backend \ -setup { setup } -body { tsv::array isbound a } -cleanup { cleanup } -result {1} test tsv-$backend-1.1 {tsv::array bind - empty} \ -constraints have_$backend \ -setup { setup } -body { tsv::array names b } -cleanup { cleanup } -result {} test tsv-$backend-1.2 {tsv::set} \ -constraints have_$backend \ -setup { setup } -body { tsv::set a Key Val } -cleanup { cleanup } -result {Val} test tsv-$backend-1.3 {tsv::get - previously set was persisted} \ -constraints have_$backend \ -setup { setup } -body { tsv::get a Key } -cleanup { cleanup } -result {Val} test tsv-$backend-1.4 {tsv::array names - previously set was persisted} \ -constraints have_$backend \ -setup { setup } -body { tsv::array names a } -cleanup { cleanup } -result {Key} test tsv-$backend-1.5 {tsv::exists - previously set exists} \ -constraints have_$backend \ -setup { setup } -body { tsv::exists a Key } -cleanup { cleanup } -result {1} test tsv-$backend-1.6 {tsv::pop - get previously set} \ -constraints have_$backend \ -setup { setup } -body { tsv::pop a Key } -cleanup { cleanup } -result {Val} test tsv-$backend-1.7 {tsv::exists - popped was removed} \ -constraints have_$backend \ -setup { setup } -body { tsv::exists a Key } -cleanup { cleanup } -result {0} file delete -force $db } ::tcltest::cleanupTests |
Changes to win/makefile.vc.
︙ | ︙ |
Changes to win/nmakehlp.c.
︙ | ︙ | |||
602 603 604 605 606 607 608 | /* * Build a list of substutitions from the first filename */ sp = fopen(substitutions, "rt"); if (sp != NULL) { while (fgets(szBuffer, cbBuffer, sp) != NULL) { | | | | | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 | /* * Build a list of substutitions from the first filename */ sp = fopen(substitutions, "rt"); if (sp != NULL) { while (fgets(szBuffer, cbBuffer, sp) != NULL) { unsigned char *ks, *ke, *vs, *ve; ks = (unsigned char*)szBuffer; while (ks && *ks && isspace(*ks)) ++ks; ke = ks; while (ke && *ke && !isspace(*ke)) ++ke; vs = ke; while (vs && *vs && isspace(*vs)) ++vs; ve = vs; while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve; *ke = 0, *ve = 0; list_insert(&substPtr, (char*)ks, (char*)vs); } fclose(sp); } /* debug: dump the list */ #ifdef _DEBUG { |
︙ | ︙ |
Changes to win/pkg.vc.
|
| | | | | 1 2 3 4 5 6 | # remember to change configure.ac as well when these change # (then re-autoconf) PACKAGE_MAJOR = 2 PACKAGE_MINOR = 8 PACKAGE_VERSION = "2.8.0" |
Changes to win/rules.vc.
︙ | ︙ |