Andreas Kupries | 1 Feb 20:26
Picon

Fwd: [Jim-devel] Backporting code from Redis to Jim Tcl


-------- Original Message --------
Subject: [Jim-devel] Backporting code from Redis to Jim Tcl
Date: Wed, 1 Feb 2012 20:07:20 +0100
From: Salvatore Sanfilippo <antirez@...>
Reply-To: Jim Tcl Development <jim-devel@...>
To: jim-devel@...

Hello,

I was surfing the Jim Tcl source code tonight, and encountered an
implementation of the hash table that is basically what is now
'dict.c/h' in Redis.
I'm not aware of bugs in this code, but the new code in Redis supports
a feature that may be interesting for embedded systems, and is not
significantly larger than the implementation used for Jim Tcl:

$ wc -l dict.[ch]
      766 dict.c
      173 dict.h
      939 total

The current Jim Tcl hash table is 923 lines of code, so the two
implementations are comparable in size.

However the new implementation offers an advantage that may be very
interesting in embedded / real-time systems, that is, it does not need
to block when rehashing, since the rehashing is performed
incrementally. This means that some more memory is used during the
rehashing as if the current table is, for instance, 64 buckets, we
(Continue reading)

Brian Griffin | 4 Feb 20:43
Favicon

Pthread+NotifierThreadProc problem

Hi Experts!

We noticed a serious problem when moving to threaded Tcl, the cost of [update] is killing our performance.  
Has anyone dug into this problem to figure out what's going on?  

Here's the testcase:

$ cat time_update.tcl
puts $tcl_patchLevel
parray tcl_platform
set i 0; puts "with update: [time {while {$i < 1000000} {incr i; update}}]"
set i 0; puts "without update: [time {while {$i < 1000000} {incr i}}]"
exit


Here's some numbers:

ActiveTcl8.5.11.0.295402-linux-ix86-threaded:
$ tclsh8.5 time_update.tcl
8.5.11
tcl_platform(byteOrder)   = littleEndian
tcl_platform(machine)     = x86_64
tcl_platform(os)          = Linux
tcl_platform(osVersion)   = 2.6.16.60-0.21-smp
tcl_platform(platform)    = unix
tcl_platform(pointerSize) = 4
tcl_platform(threaded)    = 1
tcl_platform(user)        = bgriffin
tcl_platform(wordSize)    = 4
with update: 27683665 microseconds per iteration
without update: 371879 microseconds per iteration

Local threaded build of 8.5.8:
$ tclsh8.5 time_update.tcl                                    <
8.5.8
tcl_platform(byteOrder)   = littleEndian
tcl_platform(machine)     = x86_64
tcl_platform(os)          = Linux
tcl_platform(osVersion)   = 2.6.16.60-0.21-smp
tcl_platform(platform)    = unix
tcl_platform(pointerSize) = 4
tcl_platform(threaded)    = 1
tcl_platform(user)        = bgriffin
tcl_platform(wordSize)    = 4
with update: 27861736 microseconds per iteration
without update: 346516 microseconds per iteration


Local non-threaded build of 8.4.14:
$ tclsh8.4 time_update.tcl                               <
8.4.14
tcl_platform(byteOrder) = littleEndian
tcl_platform(machine)   = x86_64
tcl_platform(os)        = Linux
tcl_platform(osVersion) = 2.6.16.60-0.21-smp
tcl_platform(platform)  = unix
tcl_platform(user)      = bgriffin
tcl_platform(wordSize)  = 4
with update: 706942 microseconds per iteration
without update: 235005 microseconds per iteration

------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
_______________________________________________
Tcl-Core mailing list
Tcl-Core@...
https://lists.sourceforge.net/lists/listinfo/tcl-core
Brian Griffin | 6 Feb 17:48
Favicon

Re: Pthread+NotifierThreadProc problem

Performing an strace on the testcase, I see the following:

No threads:
select(6, [3 5], [], [], {0, 616839372086260600}) = 0 (Timeout)

With threads:
[pid 10935] write(4, "\0", 1)           = 1
[pid 10936] <... select resumed> )      = 1 (in [3])
[pid 10935] futex(0x8e8c13c, FUTEX_WAIT, 3, NULL <unfinished ...>
[pid 10936] read(3, "\0", 1)            = 1
[pid 10936] select(8, [3 5 7], [], [], {0, 12884901888}) = 0 (Timeout)
[pid 10936] futex(0x8e8c13c, 0x4 /* FUTEX_??? */, 1 <unfinished ...>
[pid 10935] <... futex resumed> )       = 0
[pid 10936] <... futex resumed> )       = 1
[pid 10935] futex(0x8bc6418, FUTEX_WAIT, 2, NULL <unfinished ...>
[pid 10936] futex(0x8bc6418, FUTEX_WAKE, 1 <unfinished ...>
[pid 10935] <... futex resumed> )       = -1 EAGAIN (Resource temporarily unavailable)
[pid 10936] <... futex resumed> )       = 0
[pid 10935] futex(0x8bc6418, FUTEX_WAKE, 1 <unfinished ...>
[pid 10936] select(8, [3], [], [], NULL <unfinished ...>
[pid 10935] <... futex resumed> )       = 0


This explains the additional overhead in [update].  Why is it done this way?  Isn't there a better way to do this?
For example, couldn't each thread only write the pipe when there is an event?  Then each thread would look just like the non-thread version where the only sys call is a select().  

-Brian

On Feb 4, 2012, at 11:43 AM, Brian Griffin wrote:

Hi Experts!

We noticed a serious problem when moving to threaded Tcl, the cost of [update] is killing our performance.  
Has anyone dug into this problem to figure out what's going on?  

Here's the testcase:

$ cat time_update.tcl
puts $tcl_patchLevel
parray tcl_platform
set i 0; puts "with update: [time {while {$i < 1000000} {incr i; update}}]"
set i 0; puts "without update: [time {while {$i < 1000000} {incr i}}]"
exit


Here's some numbers:

ActiveTcl8.5.11.0.295402-linux-ix86-threaded:
$ tclsh8.5 time_update.tcl
8.5.11
tcl_platform(byteOrder)   = littleEndian
tcl_platform(machine)     = x86_64
tcl_platform(os)          = Linux
tcl_platform(osVersion)   = 2.6.16.60-0.21-smp
tcl_platform(platform)    = unix
tcl_platform(pointerSize) = 4
tcl_platform(threaded)    = 1
tcl_platform(user)        = bgriffin
tcl_platform(wordSize)    = 4
with update: 27683665 microseconds per iteration
without update: 371879 microseconds per iteration

Local threaded build of 8.5.8:
$ tclsh8.5 time_update.tcl                                    <
8.5.8
tcl_platform(byteOrder)   = littleEndian
tcl_platform(machine)     = x86_64
tcl_platform(os)          = Linux
tcl_platform(osVersion)   = 2.6.16.60-0.21-smp
tcl_platform(platform)    = unix
tcl_platform(pointerSize) = 4
tcl_platform(threaded)    = 1
tcl_platform(user)        = bgriffin
tcl_platform(wordSize)    = 4
with update: 27861736 microseconds per iteration
without update: 346516 microseconds per iteration


Local non-threaded build of 8.4.14:
$ tclsh8.4 time_update.tcl                               <
8.4.14
tcl_platform(byteOrder) = littleEndian
tcl_platform(machine)   = x86_64
tcl_platform(os)        = Linux
tcl_platform(osVersion) = 2.6.16.60-0.21-smp
tcl_platform(platform)  = unix
tcl_platform(user)      = bgriffin
tcl_platform(wordSize)  = 4
with update: 706942 microseconds per iteration
without update: 235005 microseconds per iteration


------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
_______________________________________________
Tcl-Core mailing list
Tcl-Core@...
https://lists.sourceforge.net/lists/listinfo/tcl-core
Andreas Kupries | 6 Feb 18:02
Picon

It begins - Fwd: Google Summer of Code 2012 Announced


-------- Original Message --------
Subject: 	Google Summer of Code 2012 Announced
Date: 	Sat, 4 Feb 2012 08:43:11 -0800
From: 	Carol Smith <carols@...>
Reply-To: 	google-summer-of-code-announce@...
To: 	Google Summer of Code Announce
<google-summer-of-code-announce@...>

Hi all,

We're pleased to announce that Google Summer of Code will be happening for its
eighth year this year. Please check out the blog post [1] about the program and
read the FAQs [2] and Timeline [3] on Melange for more information.

[1] -
http://google-opensource.blogspot.com/2012/02/google-summer-of-code-2012-is-on.html
[2] -
http://www.google-melange.com/gsoc/document/show/gsoc_program/google/gsoc2012/faqs
[3] - http://www.google-melange.com/gsoc/events/google/gsoc2012

Cheers,
Carol

--

-- 
You received this message because you are subscribed to the Google Groups
"Google Summer of Code Announce" group.
To post to this group, send email to
google-summer-of-code-announce@...
To unsubscribe from this group, send email to
google-summer-of-code-announce+unsubscribe@...
For more options, visit this group at
http://groups.google.com/group/google-summer-of-code-announce?hl=en.

------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
Alexandre Ferrieux | 6 Feb 21:30
Picon

Re: Pthread+NotifierThreadProc problem

On Mon, Feb 6, 2012 at 5:48 PM, Brian Griffin
<brian_griffin@...> wrote:
> Performing an strace on the testcase, I see the following:
>
> No threads:
> select(6, [3 5], [], [], {0, 616839372086260600}) = 0 (Timeout)
>
> With threads:
> [pid 10935] write(4, "\0", 1)           = 1
> [pid 10936] <... select resumed> )      = 1 (in [3])
> [pid 10935] futex(0x8e8c13c, FUTEX_WAIT, 3, NULL <unfinished ...>
> [pid 10936] read(3, "\0", 1)            = 1
> [pid 10936] select(8, [3 5 7], [], [], {0, 12884901888}) = 0 (Timeout)
> [pid 10936] futex(0x8e8c13c, 0x4 /* FUTEX_??? */, 1 <unfinished ...>
> [pid 10935] <... futex resumed> )       = 0
> [pid 10936] <... futex resumed> )       = 1
> [pid 10935] futex(0x8bc6418, FUTEX_WAIT, 2, NULL <unfinished ...>
> [pid 10936] futex(0x8bc6418, FUTEX_WAKE, 1 <unfinished ...>
> [pid 10935] <... futex resumed> )       = -1 EAGAIN (Resource temporarily
> unavailable)
> [pid 10936] <... futex resumed> )       = 0
> [pid 10935] futex(0x8bc6418, FUTEX_WAKE, 1 <unfinished ...>
> [pid 10936] select(8, [3], [], [], NULL <unfinished ...>
> [pid 10935] <... futex resumed> )       = 0
>
>
> This explains the additional overhead in [update].  Why is it done this way?
>  Isn't there a better way to do this?
> For example, couldn't each thread only write the pipe when there is an
> event?  Then each thread would look just like the non-thread version where
> the only sys call is a select().

The current method is unfortunately a local optimum because we also
want inter-thread communication to happen.
Indeed, if all threads were oblivious of each other, we could get away
with independent select()s (IOW, N copies of the unthreaded notifier
as you said).
But to allow for thread::send, things get tricky:

      - either burn two fds per thread (with a dedicated pipe)
      - or use non-IO synchronization like semaphores/pthread_conds

The latter was chosen because it is cheaper ( a pthread_cond is
essentially a few bytes of memory with a few small atomic-access
futex()  functions in the kernel).

It works this way:

  - a central ancillary Notifier thread centralizes in a single
select() (or soon poll/epoll, thanks to Donal) the whole process's
interest in IO events.
  - all normal threads in vwait (resp update) sit in a blocking (resp.
transiently call a nonblocking) pthread_condwait, waiting for news
from the Notifier thread
  - when it detects new IO activity, the Notifier thread does a
pthread_condsignal to wake up the interested threads
  - the notifier pipe is the reverse communication channel, allowing
all threads to tell the Notifier that their interest has changed.

I have sympathy for your weariness about this method. It would be SO
nice to just reuse the ultra-stable, straightforward unthreaded
notifier, just adding one isolated trick for interthread
communication.
One option that comes to mind is pthread_kill ( a thread-accurate
variant of signal posting ), but its lack of portability spoils it
entirely.
Another method would have been to explicitly require the preparation
of interthread communication channels (which could even be regular
[chan pipe]s).
But this would simply not be compatible with the currently documented
script API.
Alas.

-Alex

------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
Brian Griffin | 6 Feb 22:24
Favicon

Re: Pthread+NotifierThreadProc problem

On Feb 6, 2012, at 12:30 PM, Alexandre Ferrieux wrote:

> On Mon, Feb 6, 2012 at 5:48 PM, Brian Griffin
<brian_griffin@...> wrote:
>> Performing an strace on the testcase, I see the following:
>> 
>> No threads:
>> select(6, [3 5], [], [], {0, 616839372086260600}) = 0 (Timeout)
>> 
>> With threads:
>> [pid 10935] write(4, "\0", 1)           = 1
>> [pid 10936] <... select resumed> )      = 1 (in [3])
>> [pid 10935] futex(0x8e8c13c, FUTEX_WAIT, 3, NULL <unfinished ...>
>> [pid 10936] read(3, "\0", 1)            = 1
>> [pid 10936] select(8, [3 5 7], [], [], {0, 12884901888}) = 0 (Timeout)
>> [pid 10936] futex(0x8e8c13c, 0x4 /* FUTEX_??? */, 1 <unfinished ...>
>> [pid 10935] <... futex resumed> )       = 0
>> [pid 10936] <... futex resumed> )       = 1
>> [pid 10935] futex(0x8bc6418, FUTEX_WAIT, 2, NULL <unfinished ...>
>> [pid 10936] futex(0x8bc6418, FUTEX_WAKE, 1 <unfinished ...>
>> [pid 10935] <... futex resumed> )       = -1 EAGAIN (Resource temporarily
>> unavailable)
>> [pid 10936] <... futex resumed> )       = 0
>> [pid 10935] futex(0x8bc6418, FUTEX_WAKE, 1 <unfinished ...>
>> [pid 10936] select(8, [3], [], [], NULL <unfinished ...>
>> [pid 10935] <... futex resumed> )       = 0
>> 
>> 
>> This explains the additional overhead in [update].  Why is it done this way?
>>  Isn't there a better way to do this?
>> For example, couldn't each thread only write the pipe when there is an
>> event?  Then each thread would look just like the non-thread version where
>> the only sys call is a select().
> 
> The current method is unfortunately a local optimum because we also
> want inter-thread communication to happen.
> Indeed, if all threads were oblivious of each other, we could get away
> with independent select()s (IOW, N copies of the unthreaded notifier
> as you said).
> But to allow for thread::send, things get tricky:
> 
>      - either burn two fds per thread (with a dedicated pipe)
>      - or use non-IO synchronization like semaphores/pthread_conds
> 
> The latter was chosen because it is cheaper ( a pthread_cond is
> essentially a few bytes of memory with a few small atomic-access
> futex()  functions in the kernel).
> 
> It works this way:
> 
>  - a central ancillary Notifier thread centralizes in a single
> select() (or soon poll/epoll, thanks to Donal) the whole process's
> interest in IO events.
>  - all normal threads in vwait (resp update) sit in a blocking (resp.
> transiently call a nonblocking) pthread_condwait, waiting for news
> from the Notifier thread
>  - when it detects new IO activity, the Notifier thread does a
> pthread_condsignal to wake up the interested threads
>  - the notifier pipe is the reverse communication channel, allowing
> all threads to tell the Notifier that their interest has changed.
> 
> I have sympathy for your weariness about this method. It would be SO
> nice to just reuse the ultra-stable, straightforward unthreaded
> notifier, just adding one isolated trick for interthread
> communication.
> One option that comes to mind is pthread_kill ( a thread-accurate
> variant of signal posting ), but its lack of portability spoils it
> entirely.
> Another method would have been to explicitly require the preparation
> of interthread communication channels (which could even be regular
> [chan pipe]s).
> But this would simply not be compatible with the currently documented
> script API.
> Alas.

Thanks Alex, this helps.  I guess the message is Abandon all hope, ye who enter here.

We currently use SIGIO in one situation to flag when to call Tcl_DoOneEvent().  I mighty try this out more
broadly to see if it can improve the performance.

Thanks,
-Brian

------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
Kevin Kenny | 11 Feb 19:01
Picon

TIP #395: New 'string is entier' Command

Voting is closed on TIP #395: New 'string is entier' Command

Vote summary:

YES: English, Fellows, Hobbs, Kenny, Porter, Sofer
NO:
ABSTAIN: Nijtmans

TIP #395 PASSES, 6-0-1.

--

-- 
73 de ke9tv/2, Kevin

------------------------------------------------------------------------------
Virtualization & Cloud Management Using Capacity Planning
Cloud computing makes use of virtualization - but cloud computing 
also focuses on allowing computing to be delivered as a service.
http://www.accelacomm.com/jaw/sfnl/114/51521223/
Kevin Kenny | 13 Feb 01:39
Picon
Favicon

TIP #396: Symmetric Coroutines, Multiple Args, and yieldto


 TIP #396: SYMMETRIC COROUTINES, MULTIPLE ARGS, AND YIELDTO 
============================================================
 Version:      $Revision: 1.2 $
 Author:       Kevin Kenny <kennykb_at_acm.org>
 State:        Draft
 Type:         Project
 Tcl-Version:  8.6
 Vote:         Pending
 Created:      Saturday, 11 February 2012
 URL:          http://purl.org/tcl/tip/396.html
 WebEdit:      http://purl.org/tcl/tip/edit/396
 Post-History: 
 Obsoletes:    TIP #372

-------------------------------------------------------------------------

 ABSTRACT 
==========

 A new command, *yieldto*, is proposed that allows a corouting to 
 suspend its execution and tailcall into an arbitrary command. If the 
 new command is another coroutine's resume command, we obtain symmetric 
 coroutines. If the new command is the *return* command, we obtain the 
 ability for a coroutine to present an unusual status (e.g., /error/, 
 /break/, /continue/ or /return/) to its caller. The *yieldto* command 
 also marshals the arguments as a list when the yielding coroutine is 
 next invoked, allowing for the transmission of multiple arguments. 

 RATIONALE 
===========

 Several TIPS (at least [TIP #372], [TIP #373], [TIP #375], and [TIP 
 #383]) have been advanced to propose various improvements to the 
 coroutine control transfer provided by the *yield* command. This TIP 
 attempts to distill the requirements of these TIPs into an irreducible 
 minimum for implementation in 8.6 (resolving a blocking issue for an 
 8.6 release). 

 This TIP intentionally leaves out of scope some of the more complex or 
 controversial issues, such as enhancements to *info args* and *info 
 default*, unusual return from a `yield` operation. and code injection 
 into coroutines. It is believed that all of these can be added later, 
 without introducing needless incompatibilities into the basic 
 mechanisms of coroutine construction, invocation, and yielding. 

 Requirements that are thought to be essential for this TIP include: 

 *The ability for a coroutine invocation to implement anything an 
 ordinary Tcl command can do.* A coroutine invocation must be able to 
 return an error status or another unusual status (e.g., /break/, 
 /continue/ or /return/) to its caller, and to perform a tailcall. 

 *The ability for a coroutine invocation to accept multiple arguments.* 
 If a coroutine is to model a non-coroutine-based Tcl command, it must 
 be able to accept that command's arguments. 

 *Support for symmetric coroutines.* Although it is well known that 
 asymmetric coroutines (such as Tcl 8.6 implements today) and symmetric 
 coroutines have equivalent power, the implementation of symmetric 
 coroutines in a system that supports only asymmetric ones is possible 
 only by coding a separate scheduler that allows an active coroutine to 
 detach with a request to resume another. If symmetric coroutines are 
 not implemented directly, it is likely that multiple incompatible 
 schedulers will spring up in user code, greatly impeding a later 
 unification. 

 PROPOSAL 
==========

 The new command: 

       *yieldto* /cmd/ ?/arg1.../? 

 shall accept one or more arguments: 

       /cmd/ - The name of a command to invoke in place of the current 
       coroutine invocation. 

       /arg1.../ - The arguments to pass to the given command. 

 It shall have the following effects: 

    1. The current coroutine shall suspend its execution in the same way 
       as with the *yield* command. 

    2. The /cmd/ argument shall be resolved in the current coroutine's 
       context, resulting in a command to invoke. If resolution fails, 
       the error is presented in the coroutine's context. 

    3. The command that invokes the coroutine shall be placed into a 
       state such that it will accept multiple arguments when it is next 
       invoked, rather than the single argument demanded by *yield*. 

    4. The command and arguments shall be invoked in just the same way 
       as if they had been called directly from the coroutine's caller. 
       The given command replaces the coroutine invocation on the 
       runtime stack. Data and status returned from the given command 
       are returned to the context that invoked the coroutine. 

 In other words, *yieldto* means "suspend the current coroutine and 
 *tailcall* the given command: *yieldto* is to *yield* as *tailcall* is 
 to *return*." In addition, *yieldto* causes the current coroutine to 
 accept multiple arguments on its next invocation. 

 RELATIONSHIP WITH THE EARLIER PROPOSALS 
=========================================

 [TIP #372] proposes a *yieldm* command that allows a coroutine to yield 
 and subsequently accept multiple arguments when resumed. The requested 
 functionality of [TIP #372] can be layered trivially atop this 
 proposal: a one-line implementation of the *yieldm* command would be: 

       interp alias {} yieldm {} yieldto return -level 0 

 [TIP #373] proposed *yieldto* together with a separate *yieldset* 
 command. The latter allowed a coroutine to designate a set of arguments 
 and defaults. The advantage over simply passing the arguments as a list 
 was that error messages for incorrect numbers of arguments could be 
 generated automatically, and that *info args* and *info body* could 
 introspect into the desired argument list. Since the error message 
 generation can be done readily by auxiliary procedures, and the 
 introspection is something of a nicety, this proposal defers the 
 implementation of *yieldset*. 

 [TIP #375], which replaced [TIP #373], proposed a *yieldto* command 
 that is the same as the current proposal's, except that it could 
 transmit only a single argument when the coroutine was resumed. As 
 such, it was incomplete as it stands. 

 [TIP #387] proposed a unified syntax for all of the above TIPs. The 
 proposed syntax was quite complex, and its only advantage over the 
 current proposal is that is allowed for introspection using *info args* 
 and *info body* and for automatic generation of error messages for 
 incorrect arguments. Since these are regarded as something of a nicety, 
 the author of the current proposal believes that their consideration 
 can be deferred in favour of the current proposal. 

 The related [TIP #383] addresses a different set of issues: injecting 
 code into a suspended coroutine for the purpose of debugging. Its 
 implementation can be decided on independently of this TIP. 

 EXAMPLES: 
===========

 1. MULTIPLE ARGUMENTS AND ERROR RETURNS. 
------------------------------------------

 Let us assume that there is a coroutine *foo* that wishes to accept at 
 each invocation two arguments *bar* and *grill*. It therefore needs to 
 accept multiple arguments, and to check the number of arguments, 
 returning an error to its caller if they are incorrect. Code structured 
 like the following can serve both purposes: 

    # presume that $value is the value to return to the last invocation
    for {set args [yieldto return -level 0 $value]} \
        {[llength $args] != 2} \
        {set args [yieldto return -level 0 -code error \
                       -errorCode {MYCORO WRONGNUMARGS} \
                       "wrong # args, should be \"foo bar grill\""]} {
            # do nothing
    }
    lassign $args bar grill

 2. SYMMETRIC COROUTINES. 
--------------------------

 It may not be obvious from the foregoing discussion that the original 
 purpose of *yieldto* was imagined to be passing of control between peer 
 coroutines. For instance, if we assume that there are two coroutines, 
 *producer* and *consumer*, and that calling *producer* returns a string 
 while calling *consumer* accepts a string and returns nothing, then 
 each coroutine may yield to the other: 

 /Code in/ *producer*: 

    yieldto consumer $string

 /Code in/ *consumer*: 

    lassign [yieldto producer] string

 IMPLEMENTATION NOTES 
======================

 The *yieldto return* idiom is expected to be used widely, since it is 
 the way to present unusual status codes, and internally is used in the 
 implementation of *yieldm*. For this reason, the implementation may 
 contain code to optimize it specially. 

 ACKNOWLEDGMENTS 
=================

 The implementation of this TIP, and most of the details of its 
 specification, are actually the brainchild of Miguel Sofer, who 
 expresses a continued interest in seeing it implemented while being 
 unwilling at the present time to shepherd it through the sometimes 
 acrimonious discussions on tcl-core. To him belongs all the credit for 
 the ideas: any errors in the specification as presented here are the 
 author's. 

 COPYRIGHT 
===========

 This document has been placed in the public domain. 

-------------------------------------------------------------------------

 TIP AutoGenerator - written by Donal K. Fellows 

------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
Donal K. Fellows | 13 Feb 10:58
Picon
Favicon
Gravatar

TIP #397: Extensible Object Copying


 TIP #397: EXTENSIBLE OBJECT COPYING 
=====================================
 Version:      $Revision: 1.1 $
 Author:       Donal K. Fellows <donal.k.fellows_at_manchester.ac.uk>
 State:        Draft
 Type:         Project
 Tcl-Version:  8.6
 Vote:         Pending
 Created:      Monday, 13 February 2012
 URL:          http://purl.org/tcl/tip/397.html
 WebEdit:      http://purl.org/tcl/tip/edit/397
 Post-History: 

-------------------------------------------------------------------------

 ABSTRACT 
==========

 This TIP proposes a mechanism whereby an object or class can provide 
 additional control over how it gets copied to a new one by the 
 *oo::copy* command. 

 RATIONALE 
===========

 I always knew that TclOO's *oo::copy* command was not particularly 
 complete, in that only the C-level state was copied. The vast majority 
 of state associated with an object (notably including its variables) 
 was not copied on the grounds that the caller of *oo::copy* could do 
 that for themselves. However, this has not proved particularly workable 
 in practice once someone actually started to use the mechanism. It 
 turns out that the callers of *oo::copy* expect a full copy of the 
 object to be created. 

 This is quite challenging because some things associated with an object 
 are tricky to copy correctly. For example, if an object has a number of 
 Tk widgets under its control, or has timer callbacks set up, these are 
 very challenging for a generic object copying scheme to detect (and 
 generic copying of Tcl commands is difficult anyway). Fortunately, we 
 already have a mechanism for handling such per-object variation: 
 methods. 

 PROPOSED CHANGE 
=================

 I propose that the *oo::copy* command will internally call the newly 
 created object's *<cloned>* method (passing in the name of the source 
 object as the only argument) to allow for the customization of the 
 copy. If the method fails (throws an exception), the copy will be 
 destroyed and the error propagated. 

       /copiedObject/ *<cloned>* /sourceObject/ 

 Furthermore, a default implementation of the *<cloned>* method will be 
 created in *oo::object* which will duplicate the variables and 
 procedures (note, not other commands) of the source to the copy. This 
 method will not be exported by default (nor should it be; the method is 
 not intended to be called directly). 

 REFERENCE IMPLEMENTATION 
==========================

 See the "development-rfe3485060" branch of the tcloo repository: 
 <URL:https://core.tcl.tk/tcloo/timeline?r=development-rfe3485060> 

 COPYRIGHT 
===========

 This document has been placed in the public domain. 

-------------------------------------------------------------------------

 TIP AutoGenerator - written by Donal K. Fellows 

------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
Donal K. Fellows | 13 Feb 14:10
Picon
Favicon
Gravatar

Re: TIP #396: Symmetric Coroutines, Multiple Args, and yieldto

On 13/02/2012 00:39, Kevin Kenny wrote:
>   The new command:
>
>         *yieldto* /cmd/ ?/arg1.../?
>
>   shall accept one or more arguments:
>
>         /cmd/ - The name of a command to invoke in place of the current
>         coroutine invocation.
>
>         /arg1.../ - The arguments to pass to the given command.
>
>   It shall have the following effects:
[...]
>      3. The command that invokes the coroutine shall be placed into a
>         state such that it will accept multiple arguments when it is next
>         invoked, rather than the single argument demanded by *yield*.
[...]
>   In other words, *yieldto* means "suspend the current coroutine and
>   *tailcall* the given command: *yieldto* is to *yield* as *tailcall* is
>   to *return*." In addition, *yieldto* causes the current coroutine to
>   accept multiple arguments on its next invocation.

Just to check, is the proposal that the result of [yieldto] be the list
of arguments that were provided to the coroutine's resumption command? I
ask because the TIP omits that information (even though it is a logical
thing to do).

Donal.
Attachment (donal_k_fellows.vcf): text/x-vcard, 242 bytes
------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
_______________________________________________
Tcl-Core mailing list
Tcl-Core@...
https://lists.sourceforge.net/lists/listinfo/tcl-core

Gmane