.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Thread::Tie 3pm" .TH Thread::Tie 3pm "2022-10-14" "perl v5.34.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Thread::Tie \- tie variables into a thread of their own .SH "VERSION" .IX Header "VERSION" This documentation describes version 0.15. .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Thread::Tie; # use as early as possible for maximum memory savings \& \& # use default thread + tieing + create thread when needed \& tie $scalar, \*(AqThread::Tie\*(Aq; \& tie @array, \*(AqThread::Tie\*(Aq; \& tie %hash, \*(AqThread::Tie\*(Aq; \& tie *HANDLE, \*(AqThread::Tie\*(Aq; \& \& # use alternate implementation \& tie $scalar, \*(AqThread::Tie\*(Aq, \& { module => \*(AqOwn::Tie::Implementation\*(Aq, # used automatically \& use => \*(AqUse::This::Module::Also\*(Aq, # optional, also as [] \& eval => \*(Aqarbitrary Perl code\*(Aq, # optional \& }; \& \& # initialize right away \& tie $scalar, \*(AqThread::Tie\*(Aq, {}, 10; \& tie @array, \*(AqThread::Tie\*(Aq, {}, qw(a b c); \& tie %hash, \*(AqThread::Tie\*(Aq, {}, (a => \*(AqA\*(Aq, b => \*(AqB\*(Aq, c => \*(AqC\*(Aq); \& tie *HANDLE, \*(AqThread::Tie\*(Aq, {},\*(Aq>:layer\*(Aq,\*(Aqfilename\*(Aq; \& \& # create an alternate thread and use that \& my $tiethread = Thread::Tie::Thread\->new; \& tie $scalar, \*(AqThread::Tie\*(Aq, {thread => $tiethread}; \& \& # object methods \& my $tied = tie stuff,\*(AqThread::Tie\*(Aq,parameters; \& my $tied = tied( stuff ); \& my $semaphore = $tied\->semaphore; # scalar for lock()ing tied variable \& my $module = $tied\->module; # module tied to in thread \& my $tiethread = $tied\->thread; # thread to which variable is tied \& \& my $tid = $tiethread\->tid; # thread id of tied thread \& my $thread = $tiethread\->thread; # actual "threads" thread \& \& untie( stuff ); # calls DESTROY in thread, cleans up thoroughly \& \& Thread::Tie\->shutdown; # shut down default handling thread \& $tiethread\->shutdown; # shut down specific thread .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" .Vb 1 \& *** A note of CAUTION *** \& \& This module only functions on Perl versions 5.8.0 and later. \& And then only when threads are enabled with \-Dusethreads. It \& is of no use with any version of Perl before 5.8.0 or without \& threads enabled. \& \& ************************* .Ve .PP The standard shared variable scheme used by Perl, is based on tie-ing the variable to some very special dark magic. This dark magic ensures that shared variables, which are copied just as any other variable when a thread is started, update values in all of the threads where they exist as soon as the value of a shared variable is changed. .PP Needless to say, this could use some improvement. .PP The Thread::Tie module is a proof-of-concept implementation of another approach to shared variables. Instead of having shared variables exist in all the threads from which they are accessible, shared variable exist as \*(L"normal\*(R", unshared variables in a separate thread. Only a tied object exists in each thread from which the shared variable is accessible. .PP Through the use of a client-server model, any thread can fetch and/or update variables living in that thread. This client-server functionality is hidden under the hood of \fBtie()\fR. So you could say that one dark magic (the current shared variables implementation) is replaced by another dark magic. .PP I see the following advantages to this approach: .IP "memory usage" 2 .IX Item "memory usage" This implementation circumvents the memory leak that currently (threads::shared version 0.90) plagues any shared array or shared hash access. .IP "tieing shared variables" 2 .IX Item "tieing shared variables" Because the current implementation uses tie-ing, you can \fBnot\fR tie a shared variable. The same applies for this implementation you might say. However, it \fBis\fR possible to specify a non-standard tie implementation for use \&\fBwithin\fR the thread. So with this implementation you \fBcan\fR \f(CW\*(C`tie()\*(C'\fR a shared variable. So you \fBcould\fR tie a shared hash to a \s-1DBM\s0 file à la \&\fBdbmopen()\fR with this module. .PP Of course there are disadvantages to this approach: .IP "pure perl implementation" 2 .IX Item "pure perl implementation" This module is currently a pure perl implementation. This is ok for a proof of concept, but may need re-implementation in pure \s-1XS\s0 or in Inline::C for production use. .IP "tradeoff between cpu and memory" 2 .IX Item "tradeoff between cpu and memory" This implementation currently uses (much) more cpu than the standard shared variables implementation. Whether this would still be true when re-implemented in \s-1XS\s0 or Inline::C, remains to be seen. .SH "\fBtie()\fP" .IX Header "tie()" You cannot activate this module with a named class method. Instead, you should \fBtie()\fR a scalar, array, hash or glob (handle). The appropriate class method will then be selected for you by Perl. .PP Whether you tie a scalar, array, hash or glob, the first parameter to \fBtie()\fR, the second and third parameter (if specified) to \fBtie()\fR are always the same. And the \fBtie()\fR always returns the same thing: the blessed Thread::Tie object to which the variable is tied. You may or may not need that in your application. If you need to do \fBlock()\fRing on the tied variable, then you need the object to be able to call the semaphore method. .SS "class to tie with" .IX Subsection "class to tie with" You should always \fBtie()\fR to the class \fBThread::Tie\fR. So the second parameter should always read \fB'Thread::Tie'\fR. This parameter is \fBnot\fR optional. .SS "reference to parameter hash" .IX Subsection "reference to parameter hash" The third parameter is optional. If specified, it should be a reference to a hash with key/value pairs. The following fields may be specified in the hash. .IP "module" 2 .IX Item "module" .Vb 1 \& module => \*(AqYour::Tie::Implementation\*(Aq, .Ve .Sp The optional \*(L"module\*(R" field specifies the module to which the variable should be tied inside the thread. If there is no \*(L"module\*(R" field specified, a standard tie implementation, associated with the type of the variable, will be assumed. .Sp Please note that you should probably \fBnot\fR \fBuse()\fR the module yourself. The specified module will be \fBuse()\fRd automatically inside the thread (only), avoiding bloat in all the other threads. .IP "use" 2 .IX Item "use" .Vb 1 \& use => \*(AqAdditional::Module\*(Aq, \& \& use => [qw(Additional::Module::1 Additional::Module::2)], .Ve .Sp The optional \*(L"use\*(R" field specifies one or more modules that should \fBalso\fR be loaded inside the thread before the variable is tied. These can e.g. be prerequisites for the module specified in the \*(L"module\*(R" field. .Sp A single module can be specified by its name. If you need more than one module to be \fBuse()\fRd, you can specify these in an array reference. .IP "eval" 2 .IX Item "eval" .Vb 1 \& eval => \*(Aqany Perl code that you like;\*(Aq, .Ve .Sp The optional \*(L"eval\*(R" field specifies additional Perl code that should be executed inside the thread before the variable is tied. This can e.g. be used to set up prerequisites. .Sp Please note that the code to be executed currently needs to be specified as a string that is valid in an \fBeval()\fR. .IP "thread" 2 .IX Item "thread" .Vb 1 \& thread => Thread::Tie::Thread\->new, \& \& thread => $thread, .Ve .Sp The optional \*(L"thread\*(R" field specifies the instantiated Thread::Tie::Thread object that should be used to tie the variable in. This is only needed if you want to use more than one thread to tie variables in, which could e.g. be needed if there is a conflict between different tie implementations. .Sp You can create a new thread for \fBtie()\fRing with the \*(L"new\*(R" class method of the Thread::Tie::Thread module. .PP All the other input parameters are passed through to the \fBtie()\fR implementation of your choice. If you are using the default \fBtie()\fR implementation for the type of variable that you have specified, then the input parameters have the following meaning: .IP "scalar" 2 .IX Item "scalar" .Vb 1 \& tie my $scalar,\*(AqThread::Tie\*(Aq,{},10; .Ve .Sp Initialize the tied scalar to \fB10\fR. .IP "array" 2 .IX Item "array" .Vb 1 \& tie my @array,\*(AqThread::Tie\*(Aq,{},qw(a b c); .Ve .Sp Initialize the tied array with the elements 'a', 'b' and 'c'. .IP "hash" 2 .IX Item "hash" .Vb 1 \& tie my %hash,\*(AqThread::Tie\*(Aq,{},(a => \*(AqA\*(Aq, b => \*(AqB\*(Aq, c => \*(AqC\*(Aq); .Ve .Sp Initialize the tied hash with the keys 'a', 'b' and 'c' with values that are the uppercase version of the key. .IP "glob" 2 .IX Item "glob" .Vb 1 \& tie *HANDLE,\*(AqThread::Tie\*(Aq,{},">$file"; # 2 parameter open() \& \& tie *HANDLE,\*(AqThread::Tie\*(Aq,{},\*(Aq>\*(Aq,$file; # 3 parameter open() .Ve .Sp Initialize the tied glob by calling \fBopen()\fR with the indicated parameters. .SH "CLASS METHODS" .IX Header "CLASS METHODS" There is only one named class method. .SS "shutdown" .IX Subsection "shutdown" .Vb 1 \& Thread::Tie\->shutdown; .Ve .PP The \*(L"shutdown\*(R" class method shuts down the thread that is used for variables that have been \fBtie()\fRd without specifying an explicit thread with the \*(L"thread\*(R" field. It in fact calls the \*(L"shutdown\*(R" method of the Thread::Tie::Thread module on the instantiated object of the default thread. .PP Any variables that were \fBtie()\fRd, will not function anymore. Any variables that are \fBtie()\fRd \fBafter\fR the thread was shut down, will automatically create a new default thread. .SH "OBJECT METHODS" .IX Header "OBJECT METHODS" The following object methods are available for the instantiated Thread::Tie object, as returned by the \fBtie()\fR function. .SS "semaphore" .IX Subsection "semaphore" .Vb 1 \& my $semaphore = $tied\->semaphore; \& \& my $semaphore = (tie my $variable,\*(AqThread::Tie)\->semaphore; \& \& my $semaphore = tied( $variable )\->semaphore; \& \& {lock( $semaphore ); do stuff with tied variable privately} .Ve .PP The \*(L"semaphore\*(R" object method returns a reference to a shared scalar that is associated with the tied variable. It can be used for \fBlock()\fRing access to the tied variable. Scalar values can be assigned to the shared scalar without any problem: it is not used internally for anything other than to allow the developer to \fBlock()\fR access to the tied variable. .SS "module" .IX Subsection "module" .Vb 1 \& my $module = $tied\->module; \& \& my $module = (tie my $variable,\*(AqThread::Tie)\->module; \& \& my $module = tied( $variable )\->module; .Ve .PP The \*(L"module\*(R" object method returns the name of the module to which the variable is tied inside the thread. It is the same as what was (implicitly) specified with the \*(L"module\*(R" field when the variable was tied. .SS "thread" .IX Subsection "thread" .Vb 1 \& my $tiethread = $tied\->thread; \& \& my $tiethread = (tie my $variable,\*(AqThread::Tie)\->thread; \& \& my $tiethread = tied( $variable )\->thread; .Ve .PP The \*(L"thread\*(R" object method returns the instantiated 'Thread::Tie::Thread' object to which the variable is tied. It is the same as what was (implicetely) specified with the \*(L"thread\*(R" field when the variable was tied. .SH "REQUIRED MODULES" .IX Header "REQUIRED MODULES" .Vb 2 \& load (0.11) \& Thread::Serialize (0.07) .Ve .SH "CAVEATS" .IX Header "CAVEATS" Because transport of data structures between threads is severely limited in the current threads implementation (perl 5.8.0), data structures need to be serialized. This is achieved by using the Thread::Serialize library. Please check that module for information about the limitations (of any) of data structure transport between threads. .SH "TODO" .IX Header "TODO" Examples should be added. .SH "AUTHOR" .IX Header "AUTHOR" Elizabeth Mattijsen, . .PP maintained by \s-1LNATION,\s0 .PP Please report bugs to . .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2002\-2003, 2010 Elizabeth Mattijsen , 2019 \s-1LNATION\s0 . All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. .SH "SEE ALSO" .IX Header "SEE ALSO" threads, Thread::Serialize.