Mercurial > hg > graal-compiler
diff graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyThread.java @ 13514:0fbee3eb71f0
Ruby: import project.
author | Chris Seaton <chris.seaton@oracle.com> |
---|---|
date | Mon, 06 Jan 2014 17:12:09 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyThread.java Mon Jan 06 17:12:09 2014 +0000 @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.util.*; +import java.util.concurrent.*; + +import com.oracle.truffle.ruby.runtime.objects.*; +import com.oracle.truffle.ruby.runtime.subsystems.*; + +/** + * Represents the Ruby {@code Thread} class. Implemented using Java threads, but note that there is + * not a one-to-one mapping between Ruby threads and Java threads - specifically in combination with + * fibers as they are currently implemented as their own Java threads. + */ +public class RubyThread extends RubyObject { + + /** + * The class from which we create the object that is {@code Thread}. A subclass of + * {@link RubyClass} so that we can override {@link #newInstance} and allocate a + * {@link RubyThread} rather than a normal {@link RubyBasicObject}. + */ + public static class RubyThreadClass extends RubyClass { + + public RubyThreadClass(RubyClass objectClass) { + super(null, objectClass, "Thread"); + } + + @Override + public RubyBasicObject newInstance() { + return new RubyThread(this, getContext().getThreadManager()); + } + + } + + private final ThreadManager manager; + + private final CountDownLatch finished = new CountDownLatch(1); + + private final int hashCode = new Random().nextInt(); + + public RubyThread(RubyClass rubyClass, ThreadManager manager) { + super(rubyClass); + this.manager = manager; + } + + public void initialize(RubyProc block) { + final RubyProc finalBlock = block; + + initialize(new Runnable() { + + @Override + public void run() { + finalBlock.call(null); + } + + }); + } + + public void initialize(Runnable runnable) { + final RubyThread finalThread = this; + final Runnable finalRunnable = runnable; + + new Thread(new Runnable() { + + @Override + public void run() { + finalThread.manager.registerThread(finalThread); + finalThread.manager.enterGlobalLock(finalThread); + + try { + finalRunnable.run(); + } finally { + finalThread.manager.leaveGlobalLock(); + finalThread.manager.unregisterThread(finalThread); + finalThread.finished.countDown(); + } + } + + }).start(); + } + + @Override + public int hashCode() { + return hashCode; + } + + public void shutdown() { + } + + public void join() { + final RubyThread runningThread = getRubyClass().getContext().getThreadManager().leaveGlobalLock(); + + try { + while (true) { + try { + finished.await(); + break; + } catch (InterruptedException e) { + // Await again + } + } + } finally { + runningThread.manager.enterGlobalLock(runningThread); + } + } + +}