bugKawa - Bugs: bug #14098, runnable rfe

 
 

bug #14098: runnable rfe

Submitter:  tk <huh>
Submitted:  Thu 11 Aug 2005 09:19:45 PM UTC
   
 
Category:  Scheme library Severity:  3 - Normal
Item Group:  Feature Request Status:  Fixed
Privacy:  Public Assigned to:  bothner
Open/Closed:  Closed
* Mandatory Fields

Add a New Comment Rich Markup
   

Thu 25 Aug 2005 12:45:11 AM UTC, comment #5: 

Thanks.  I checked in this patch, with a few minor changes.

I didn't include the setIndirectDefines flag.  You say it is
"closer" to 1.7 - but I don't think that was right.

We could add an optional 'shared' flag to the runnable function, just like the scheme-window function takes, but I don't think it should be the default.  Also, I'm not convinced it's needed at all.  If you disagree, perhaps you could post some use-cases on the mailing list so people can discuss it.

Per Bothner <bothner>
Group administrator
Mon 15 Aug 2005 07:15:41 PM UTC, comment #4: 

Of course. your first suggestion of having Future encapsulate an
instance of RunnableClosure makes sense.

I've attached a patch that implements Future as such.

I slipped one change into RunnableClosure that you may disagree with.
The constructor calls setIndirectDefines on the closure's environment, so
that the behavior of future is closer to that of version 1.7.
I suppose one could argue that this should be done explicitly by
code that uses runnable.

tk <huh>
Mon 15 Aug 2005 08:41:38 AM UTC, comment #3: 

Would it make sense for future to create a RunnableClosure that it passes to a Thread?  Or perhaps Future could be a bare-bones class that does little more than extend Thread and create a RunnabeClosure.  Or we could share code by calling shared static methods.

Per Bothner <bothner>
Group administrator
Fri 12 Aug 2005 03:44:58 PM UTC, comment #2: 


Thanks for taking a look at this. I wasn't happy about the code
duplication either, but there are problems with your version.
The additional space overhead of using Thread is about a dozen
private fields, and the Thread constructor adds the instance to
the current ThreadGroup. This overhead may be small compared with
the creation of the RunnableClosure, but it's more than nothing.

There's also a more serious problem. While the thread stack isn't
created until start is called, in version 1.4 JVMs (at least) the
thread isn't removed from its ThreadGroup until the thread exits,
which it can't do without being started, so you're left with a
choice of leaking memory or having to allocate the stack and
scheduling the thread before it can be reclaimed. (I haven't
checked on whether 1.5 JVMs continue this hapless approach).

I'll look at whether there's another way to refactor it; if not I'd say
a little code duplication is worth avoiding the foregoing silliness.


tk <huh>
Fri 12 Aug 2005 06:00:01 AM UTC, comment #1: 

I have a concern about the amound of duplication between RunnbaleClosure and Future.  How would this hierarchy work:

public class RunnableClosure extends Thread
public class Future extends RunnableClosure

It might even be reasonable to just use the Future class instead of a new RunnableClosure class.  Perhaps the runnable macro should just:
(define-syntax runnable
  (syntax-rules ()
    ((future expression)
     (make <gnu.mapping.Future> (lambda () expression)))))
I.e. same as Future but doesn't call start.
One issue is the name - what is printed.  An idea: Change the toString method to print #<runnable " ... before start is called and #<future ... after.

Per Bothner <bothner>
Group administrator
Thu 11 Aug 2005 09:19:45 PM UTC, original submission:  


In response to savannah bug #14072, following is a strawman implementation
of an api for creating a java.lang.Runnable from a procedure and its
environment. The implementation is based on Future.

Example usage that illustrates need for such an api:

    (let ((graphics (invoke canvas 'getGraphics)))
      (invoke-static <java.awt.EventQueue> 'invokeLater
(runnable
  (lambda ()
    (invoke graphics 'drawRect 0 0 1 1)))))
 

kawa/lib/runnable.scm:

(define (runnable (proc :: <procedure>)) :: <gnu.mapping.RunnableClosure>
  (make <gnu.mapping.RunnableClosure> proc))



gnu/mapping/RunnableClosure.java:

package gnu.mapping;

public class RunnableClosure implements Runnable
{
  Object result;
  CallContext context;
  public Environment environment;
  Throwable exception;
  Procedure action;
  String name;
  static int nrunnables=0;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name=name;
  }

  public RunnableClosure (Procedure action, CallContext parentContext)
  {
    this(action, parentContext, parentContext.getEnvironment());
  }

  public RunnableClosure (Procedure action,
                            CallContext parentContext, Environment penvironment)
  {
    setName("r"+nrunnables++);
    this.action = action;
    SimpleEnvironment env = Environment.make(getName(), penvironment);
    env.flags |= Environment.THREAD_SAFE;
    env.flags &= ~Environment.DIRECT_INHERITED_ON_SET;
    env.setIndirectDefines();   // note -- not in Future
    this.environment = env;
    int n = parentContext.pushedFluidsCount;
    for (int i = 0;  i < n; i++)
      {
        // If we're inside a fluid-let, then the child thread should inherit
        // the fluid-let binding, even if it isn't accessed in the child until
        // after the parent exits the fluid-let.  Set things up so only the
        // binding in the parent is restored, but they share utnil then.
        Location loc = parentContext.pushedFluids[i];
        Symbol name = loc.getKeySymbol();
        Object property = loc.getKeyProperty();
        if (name != null && loc instanceof NamedLocation)
          {
            NamedLocation nloc = (NamedLocation) loc;
            if (nloc.base == null)
              {
                SharedLocation sloc = new SharedLocation(name, property, 0);
                sloc.value = nloc.value;
                nloc.base = sloc;
                nloc.value = null;
                nloc = sloc;
              }
            int hash = name.hashCode() ^ System.identityHashCode(property);
            NamedLocation xloc = env.addUnboundLocation(name, property, hash);
            xloc.base = nloc;
          }
      }
  }

  public RunnableClosure (Procedure action)
  {
    this(action, CallContext.getInstance());
  }

  public RunnableClosure (Procedure action, Environment penvironment)
  {
    this(action, CallContext.getInstance(), penvironment);
  }

  /** Get the CallContext we use for this Thread. */
  public final CallContext getCallContext() { return context; }

  public void run ()
  {
    try
      {
        if (context == null)
          context = CallContext.getInstance();
        else
          CallContext.setInstance(context);
        context.curEnvironment = environment;
        result = action.apply0 ();
      }
    catch (Throwable ex)
      {
        exception = ex;
      }
  }

  public String toString() {
    StringBuffer buf = new StringBuffer();
    buf.append ("#<runnable ");
    buf.append(getName());
    buf.append(">");
    return buf.toString();
  }
}

tk <huh>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #3367:  RunnableClosure.java added by huh (3KiB - application/octet-stream - gnu/mapping/RunnableClosure.java)
file #3366:  diff.rc added by huh (9KiB - application/octet-stream - cvs diff -u patch)

 

Depends on the following items: None found

Items that depend on this one: None found

 

CC list is empty

 

There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

Only logged-in users can vote.

 

Follow 6 latest changes.

Date Changed by Updated Field Previous Value => Replaced by
2005-08-25 bothner StatusNone Fixed
    Assigned toNone bothner
    Open/ClosedOpen Closed
2005-08-15 huh Attached File- Added RunnableClosure.java, #2828
2005-08-15 huh Attached File- Added diff.rc, #2827
2005-08-11 huh Carbon-Copy- Added -email is unavailable-

Back to the top

Powered by Savane 3.13-4b48.
Corresponding source code