Advertisement
fslasht

pseudo Coroutine in Java (2)

Jul 2nd, 2011
327
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.09 KB | None | 0 0
  1. /**
  2.  * コルーチンもどき クラス
  3.  * 派生してaction()をオーバーライドして使ってね。
  4.  * @author F/T
  5.  */
  6.  
  7. package com.dokokano.shotchange.game.common;
  8.  
  9. import android.util.Log;    // for Log class
  10.  
  11. public class Corouchan implements Runnable{
  12.     Object lock_ = new Object();
  13.     Object returnLock_ = new Object();
  14.     Thread thread_;
  15.     boolean exit_ = false;
  16.     boolean exitDone_ = false;
  17.  
  18.     // スレッドスタート
  19.     public void start() {
  20.         Log.d("corouchan", "start()");
  21.         thread_ = new Thread(this);
  22.  
  23.         thread_.start();
  24.  
  25.         // スレッドがスタートするまで待つ (returnLock_がnotifyされるのを待つ)
  26.         synchronized (returnLock_) {
  27.             try {
  28.                 returnLock_.wait(1000);
  29.             } catch (InterruptedException e) {
  30.                 // run() 直後のreturnLock_.notifyAll();が早過ぎる場合はデッドロックになるかも。タイムオーバーで回避
  31.                 Log.d("corouchan", "InterruptedException@start");
  32.                 e.printStackTrace();
  33.             }
  34.  
  35.         }
  36.     }
  37.  
  38.     // スレッド終了 (終了要求を出す。即座には停止しない)
  39.     // ※これ呼んでスレッド終了しないとアプリが終わらないよ!
  40.     public void end() {
  41.         Log.d("corouchan", "end()");
  42.  
  43.         exit_ = true;
  44.         synchronized (lock_) {
  45.             lock_.notifyAll();
  46.         }
  47.     }
  48.  
  49.     // 終了要求がきているか?
  50.     public boolean isExit() {
  51.         return exit_;
  52.     }
  53.  
  54.     // 終了を完了したか?
  55.     public boolean isExitDone() {
  56.         return exitDone_;
  57.     }
  58.  
  59.     @Override
  60.     public void run() {
  61.         Log.d("corouchan", "run()");
  62.  
  63.         // 開始処理
  64.         // 呼び出し元のwaitを解除
  65.         synchronized (returnLock_) {
  66.             returnLock_.notifyAll();
  67.         }
  68.         // next()が呼ばれるまでwait
  69.         synchronized (lock_) {
  70.             try {
  71.                 lock_.wait();
  72.             } catch (InterruptedException e) {
  73.                 Log.d("corouchan", "InterruptedException@run");
  74.                 e.printStackTrace();
  75.             }
  76.         }
  77.  
  78.         // コルーチン本体(ユーザー作成部)を呼ぶ
  79.         action();
  80.  
  81.         // 終了処理
  82.         exitDone_ = true;
  83.         synchronized (returnLock_) {
  84.             returnLock_.notifyAll();
  85.         }
  86.     }
  87.  
  88.     /**
  89.      * ユーザーアクション
  90.      * ここにコルーチンで実行したい処理を記述
  91.      * yiedl() を呼ぶと呼び出し元に戻る
  92.      */
  93.     public void action() {
  94.         Log.d("corouchan", "POS1");
  95.         if ( yield() ) return;
  96.         Log.d("corouchan", "POS2");
  97.         if ( yield() ) return;
  98.         Log.d("corouchan", "POS3");
  99.         if ( yield() ) return;
  100.         Log.d("corouchan", "POS4");
  101.         if ( yield() ) return;
  102.         Log.d("corouchan", "POS5");
  103.  
  104.     }
  105.  
  106.     // コルーチンの処理を一時停止して、呼び出し元に戻る
  107.     public boolean yield() {
  108.         Log.d("corouchan", "yield()");
  109.         synchronized (returnLock_) {
  110.             returnLock_.notifyAll();
  111.         }
  112.         try {
  113.             synchronized (lock_) {
  114.                 lock_.wait(1000);           // ※呼び出し元にもどった直後next()を呼ばれると、next()内のnotify()の後に、wait()が呼ばれてデッドロックになるかもしれない
  115.             }
  116.         } catch (InterruptedException e) {
  117.             Log.d("corouchan", "InterruptedException@yield");
  118.             e.printStackTrace();
  119.         }
  120.         Log.d("corouchan", "yield() - exit");
  121.         return exit_;
  122.     }
  123.  
  124.     // コルーチンの次の処理を実行
  125.     // 戻り値: ture:成功 false:失敗(すでにコルーチンは終了しているなど)
  126.     public boolean next() {
  127.         Log.d("corouchan", "next()");
  128.         if ( exit_ || exitDone_ ) return false; // すでに終了している
  129.         try {
  130.             synchronized (returnLock_) {
  131.  
  132.                 synchronized (lock_) {
  133.                     lock_.notifyAll();
  134.                 }
  135.  
  136.                 // コルーチン内で yield()が呼ばれるまでwait
  137.                 returnLock_.wait();
  138.             }
  139.             Log.d("corouchan", "next() - exit true");
  140.             return true;
  141.         } catch (InterruptedException e) {
  142.             Log.d("corouchan", "InterruptedException@next");
  143.             e.printStackTrace();
  144.         }
  145.         Log.d("corouchan", "next() - exit false");
  146.         return false;
  147.     }
  148.  
  149. }
  150.  
  151.  
  152.  
  153. /* サンプル
  154.     Corouchan c = new Corouchan();
  155.     c.start();
  156.  
  157.     for ( int i=0; i<10; i++ ) {
  158.         c.next();       // next()を呼ぶとコルーチンに制御が戻る
  159.                         // i==4 の段階で「pos5」が出力され、以降はなにも起きない
  160.     }
  161.     c.end();
  162.  
  163. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement