In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

forked from: そうめんで Queue とか

そうめんのサンプル FlickrSphere にある PhotoImageQueue が便利なので、
なるだけ解りやすくシンプルにしてみたサンプル作ってみたよ。

@see    http://www.libspark.org/browser/as3/Thread/trunk/samples/flickrsphere/src/org/libspark/flickrsphere/threads/flickr/PhotoImageQueue.as
// forked from soundkitchen's そうめんで Queue とか
/**
 *  複数のスレッドでキューにアクセスする感じにしてみた。notify();ってこういう場面に良いわけですね。
 *
 *  @see    http://www.libspark.org/browser/as3/Thread/trunk/samples/flickrsphere/src/org/libspark/flickrsphere/threads/flickr/PhotoImageQueue.as
 */
package
{
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.events.Event;

    import org.libspark.thread.EnterFrameThreadExecutor;
    import org.libspark.thread.Thread;

    [SWF(frameRate=30, width=465, height=465, backgroundColor=0xffffff)]

    /**
     *  ドキュメントクラス
     */
    public class Tmp extends Sprite
    {
        /**
         *  コンストラクタ
         */
        public function Tmp()
        {
            //  ステージ上で会いましょう
            addEventListener(Event.ADDED_TO_STAGE, initialize);
        }

        /**
         *  初期化する
         */
        private function initialize(evt:Event):void
        {
            removeEventListener(Event.ADDED_TO_STAGE, initialize);

            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;

            //  そうめんの初期化がまだなら
            if (!Thread.isReady)
            {
                //  ココで初期化しませう
                Thread.initialize(new EnterFrameThreadExecutor());
            }

            //  ではではタスクを消化しましょう!!
            new MainThread(this).start();
        }
    }
}


import flash.display.DisplayObjectContainer;
import flash.display.Stage;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;

import org.libspark.thread.Monitor;
import org.libspark.thread.Thread;


/**
 *  メイン処理を行うスレッド
 */
internal class MainThread extends Thread
{
    private var layer:DisplayObjectContainer;

    /**
     *  コンストラクタ
     */
    public function MainThread(layer:DisplayObjectContainer)
    {
        this.layer = layer;
    }

    /**
     *  最初に実行される処理
     */
    override protected function run():void
    {
        var queue:SimpleQueue,
            fmt:TextFormat,
            txt:TextField;

        fmt = new TextFormat();
        fmt.size = 96;
        fmt.bold = true;
        fmt.font = 'sans-serif';
        fmt.color = 0x4c4c4c;

        txt = new TextField();
        txt.autoSize = TextFieldAutoSize.LEFT;
        txt.selectable = false;
        txt.defaultTextFormat = fmt;

        layer.addChild(txt);

        //  タスクを管理するキューを作成
        queue = new SimpleQueue;

        //  タスクを作るスレッドを起動
        new StackTaskThread(queue, .8).start();

        //  タスクを消化するスレッドを起動
        new OutputTaskThread(queue, txt).start();
        
        // タスク消化スレッドを起動 その2
        new OutputColordThread(queue, txt).start();
    }

    /**
     *  後始末する
     */
    override protected function finalize():void
    {
        layer = null;
    }
}


/**
 *  タスクをスタックするキュー
 */
internal class SimpleQueue
{
    private var queue:Vector.<String>;
    private var monitor:Monitor;

    /**
     *  キューが空かどうかを判別する
     */
    public function get isEmpty():Boolean
    {
        return queue.length == 0;
    }

    /**
     *  コンストラクタ
     */
    public function SimpleQueue()
    {
        queue = new Vector.<String>();
        monitor = new Monitor();
    }

    /**
     *  消化出来るタスクがあるかを判別する
     */
    public function checkPoll():Boolean
    {
        var retval:Boolean = true;

        //  キューが空なら
        if (isEmpty)
        {
            retval = false;

            //  現在のスレッドを待機させる
            monitor.wait();
        }
        return retval;
    }

    /**
     *  タスクを一つ返す
     *  ココの返り値の型が決められないがために、
     *  コイツはライブラリ化されてないんだろうなぁ。と思う
     */
    public function poll():String
    {
        //  先頭のタスクを返す
        return queue.shift();
    }

    /**
     *  新しいタスクをスタックし、それを消費者にオファーする
     */
    public function offer(value:String):void
    {
        //  与えられたタスクをスタック
        queue.push(value);

        //  待ち状態のスレッドを起こす
        monitor.notify();
    }
}


/**
 *  ひたすらキューにタスクを詰め込むスレッド
 */
internal class StackTaskThread extends Thread
{
    private var queue:SimpleQueue;
    private var threshold:Number = 0;

    /**
     *  コンストラクタ
     */
    public function StackTaskThread(queue:SimpleQueue, threshold:Number=0)
    {
        //  キューを受け取る
        this.queue = queue;

        //  スレッショルドが NaN で無ければ
        if (!isNaN(threshold))
        {
            //  設定に反映する
            this.threshold = threshold;
        }
    }

    /**
     *  最初に実行される処理
     */
    override protected function run():void
    {
        //  割り込まれてたらおしまい
        if (checkInterrupted()) return;

        //  乱数が敷居値を越えていれば
        if (Math.random() >= threshold)
        {
            var code:uint;

            //  65 ~ 90 -> a - z
            code = Math.floor(Math.random() * 26) + 65;

            //  適当な文字を一文字タスクに入れる
            queue.offer(String.fromCharCode(code));
        }

        //  次もまたこの処理を呼ぶように登録
        next(run);
    }

    /**
     *  後始末する
     */
    override protected function finalize():void
    {
        queue = null;
    }
}


/**
 *  キューにスタックされたタスクを消化するスレッド
 */
internal class OutputTaskThread extends Thread
{
    private var queue:SimpleQueue;
    private var target:TextField;
    private var stage:Stage;

    /**
     *  コンストラクタ
     */
    public function OutputTaskThread(queue:SimpleQueue, target:TextField)
    {
        this.queue = queue;
        this.target = target;
        this.stage = target.stage;
    }

    /**
     *  最初に実行される処理
     */
    override protected function run():void
    {
        //  キューにタスクがスタックされていれば
        if (queue.checkPoll())
        {
            //  それをアウトプット
            target.text = queue.poll();

            //  x, y の値をセンターに補正
            target.x = (stage.stageWidth - target.width) / 2;
            target.y = (stage.stageHeight - target.height) / 2;
        }

        //  次のタスクを登録する
        next(run);
    }

    /**
     *  後始末する
     */
    override protected function finalize():void
    {
        queue = null;
        target = null;
        stage = null;
    }
}

/**
 *  キューにスタックされたタスクを消化するスレッド その2
 */
internal class OutputColordThread extends Thread
{
    private var queue:SimpleQueue;
    private var target:TextField;
    private var stage:Stage;
    private var format:TextFormat;
    /**
     *  コンストラクタ
     */
    public function OutputColordThread(queue:SimpleQueue, target:TextField)
    {
        this.queue = queue;
        this.target = target;
        this.stage = target.stage;
        this.format = target.defaultTextFormat;
        this.format.color = '0xff0000';
    }

    /**
     *  最初に実行される処理
     */
    override protected function run():void
    {
        //  キューにタスクがスタックされていれば
        if (queue.checkPoll())
        {
            //  それをアウトプット
            target.text = queue.poll();
            target.setTextFormat(this.format);
            
            //  x, y の値をセンターに補正
            target.x = (stage.stageWidth - target.width) / 2;
            target.y = (stage.stageHeight - target.height) / 2;
        }

        //  次のタスクを登録する
        next(run);
    }

    /**
     *  後始末する
     */
    override protected function finalize():void
    {
        queue = null;
        target = null;
        stage = null;
    }
}