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

PrimeNumbersWorld

Spark projectにマルチスレッド用ライブラリを公開したので、そのサンプルコードを移植してみました。

リアルタイムに素数を検索して画面に表示していきます。

Threader
http://www.libspark.org/wiki/Threader
Get Adobe Flash player
by shohei909 28 Oct 2010
/**
 * Copyright shohei909 ( http://wonderfl.net/user/shohei909 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/ipyi
 */

package{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.text.TextField;
    import flash.utils.Timer;
    import net.hires.debug.Stats;
    
    //Threaderライブラリ
    //import org.libspark.threader.Thread;
    //import org.libspark.threader.Threader;
    
    /**
     * MIT Lisence
     * @author shohei909
     */
    [SWF(backgroundColor="0xFFFFFF",width="465",height="465",frameRate="30")]
    public class PrimeNumbersWorld extends Sprite {
        private const W:int = 465;
        private const H:int = 465;
        private var bitmapData:BitmapData = new BitmapData(W,H);
        private var textField:TextField = new TextField();
        
        function PrimeNumbersWorld() {
            
            addChild(new Bitmap(bitmapData));
            addChild(new Stats()).alpha = 0.7;
            
            textField.x = 0;
            textField.text = "2";
            textField.textColor = 0x111111;
            textField.autoSize = "left";
            drawText( bitmapData, textField );
            
            addEventListener( "enterFrame", onFrame );
            
            
            //スレッド開始
            Threader.addThread( threadMethod );
           
        }
        
        //素数の検索を行うメソッドです。
        //forやwhileの変わりにt.loopを使うことでマルチスレッドを実現します。
        private function threadMethod( t:Thread ):void {
            var primes:Array = [2];
            var i:uint = 3;
            t.loop( 
            function _():Boolean{ //ループさせる処理を記述
  
                var count:int = 0; 
                var prime:uint = primes[count];
                var flag:Boolean = true;

                t.loop( 
                function _():Boolean{ //ループさせる処理を記述
                    
                    if(  !(prime*prime <= i)  ) return false; //ループ終了
                    if( i % prime == 0 ){ flag = false; return false; }  //ループ終了
                    prime = primes[++count];
                    return true; //ループ続行    
                
                }, 
                
                function _onComplete():void { //ループ終了後に呼び出される処理を記述
                    
                    if (flag) { 
                        primes.push( i ) ;
                        textField.text = i.toString();
                        drawText( bitmapData, textField );
                    }
                    i += 2;
                    
                }); 
                
                return true; //無限ループ
            });
        }
        
        private function drawText(bitmapData:BitmapData, textField:TextField):void {
            var rate:int = Math.random()*Math.random()*Math.random()*20;
            var mtr:Matrix = new Matrix(rate,0,0,rate,( Math.random()*bitmapData.width)-(textField.width*rate/2),( Math.random() *bitmapData.height)-(textField.height*rate/2));
            bitmapData.draw(textField, mtr);
        }
        
        
        private var white:BitmapData = new BitmapData(W, H);
        private function onFrame(e:Event):void {
            bitmapData.unlock();
            bitmapData.merge(white,bitmapData.rect, new Point, 30,30,30,0);
            bitmapData.lock();
        }
        
    }
}
















//Threaderを導入した場合以下は省略してください。

//Threaderライブラリ=================================================================================
    import flash.utils.Timer;
    import flash.utils.getTimer;
    import flash.events.Event;
    /**
     * ThreadクラスはThreaderによって実行されるスレッドのクラスです。
     */
    class Thread extends Object{
        static private var threadNum:int = 0;
        
        /** スレッドの優先度を指定します。推奨される値は0-1です。すべてのスレッドの優先度が1を超えていると、理論上は処理落ちが発生します。 */
        public var rate:Number = Threader.defaultRate;
        /** スレッドが正しく完了した時に呼び出される関数です。 */
        public var onComplete:Function;
        /** onCompleteに渡すパラメーターの配列です。 */
        public var onCompleteParams:Array;
        /** スレッドが破棄される時に呼び出される関数です。 */
        public var onRemove:Function;
        /** onRemoveに渡すパラメーターの配列です */
        public var onRemoveParams:Array;
        
        /** スレッドの制限時間(ミリ秒)です。スレッドの実行時間がtimeoutを超えると、スレッドは中断されます。timeoutを0に設定すると制限時間はありません。 */
        public var timeout:uint = 0;
        /** スレッドがタイムアウトする時に呼び出される関数です。 */
        public var onTimeout:Function;
        /** onTimeoutに渡すパラメーターの配列です。 */
        public var onTimeoutParams:Array;
        /** このスレッドの待機時間です。 */
        public var delay:int = 0;
        /** このスレッドの名前です。 */
        public var name:String = "";
        
        private var _span:Number = Threader.defaultRate;
        /** このスレッドの呼び出し間隔です。 */
        public function get span():Number { return _span; }
        public function set span(s:Number):void { _span = s; _timer.delay = s; }
    
        
        private var _currentLoop:Loop = null;
        /** 現在進行中のループ処理です。 */
        public function get currentLoop():Loop { return _currentLoop; }
        
        private var _end:Boolean = false;
        /** このスレッドが終了しているかどうかのBoolean値です。 */
        public function get removed():Boolean { return _end; }
        private var _loops:Vector.<Loop> = new Vector.<Loop>();
        private var  _limit:int = 5, _startTime:int = 0, _stopTime:int = 0, _waitTime:int = 0, _added:Boolean, currentLoops:Vector.<Loop>;
        private var _timer:Timer;
        /** このスレッドが現在進行中かどうかのBoolean値です。 */
        public function get running():Boolean { return _timer.running; } 
        
        function Thread() {
            _timer = new Timer(span); 
            _startTime = getTimer();
            _timer.start();
            threadNum++;
            Threader.threads.push( this );
            _timer.addEventListener( "timer", onFrame  );
        }
        
        /**
         *  Threaderでは、loop関数で設定した関数を分割して実行することで、マルチスレッドが実現されます。
         * このとき、注意すべき点はloopMethodの一度の実行に長時間かかってしまう場合、処理落ちを起こすということです。
         * 
         * @param    loopMethod 繰り返し呼び出す関数です。この関数はfalseをかえすまで繰り返し呼び出されます。
         * @param    onComplete ループが終了したときに呼び出される関数です。
         * @param    name このループの名前です。
         */
        public function loop( loopMethod:Function, onComplete:Function = null, name:String = "" ):Loop{
            var loop:Loop = new Loop( _currentLoop, loopMethod, onComplete,name );
            if( _currentLoop == null ){ _loops.push( loop );
            }else { _currentLoop.loops.push( loop ); _added = true; }
            return loop;
        }
        
        /**
         * このスレッドを破棄します。
         */
        public function remove():void {
            if( onRemove != null ){ onRemove() }
            threadNum--; 
            Threader.threads.splice( Threader.threads.indexOf( this ), 1 );
            _end = true;
            _loops = null;
            _currentLoop = null;
            currentLoops = null;
            _timer.stop();
            _timer.removeEventListener( "timer", onFrame  );
        }
        
        /**
         * このスレッドを一時停止します。
         */
        public function pause():void 
        {
            if ( _timer.running ) { 
                _timer.stop();
                _stopTime = getTimer();
                if( delay <= 0 ){ threadNum--; }
            }
        }
        
        /**
         * このスレッドを再開します。
         */
        public function resume():void 
        {
            if ( !_timer.running ) { 
                _timer.start();
                _startTime = getTimer();
                if( delay <= 0 ){ threadNum++; }
            }
        }
        
        /**
         * 指定された時間(ミリ秒)だけスレッドを待機させます。
         */
        public function sleep( delay:int ):void 
        {
            if( delay > 0 ){
                if ( running && delay > 0 ) { threadNum--; }
                _waitTime = getTimer();
                _limit = -1; 
                this.delay = delay;
            }
        }
        
        private function onFrame(e:Event):void {
            if ( timeout != 0 && timeout <= getTimer() - _startTime ) { if(onTimeout != null ){onTimeout.apply(null,onTimeoutParams)}; remove(); return; }
            if ( delay > 0  ) {
                delay += -getTimer() + _waitTime;
                if ( delay <= 0 ) { delay = 0; threadNum++; }
                _waitTime = getTimer();
                _startTime += getTimer() - _waitTime;
            }else {
                var time:int = getTimer(); 
                _limit = Math.ceil((span * rate) / threadNum - 1);
                all: while(true){
                    if( _currentLoop == null ){
                        if ( _loops.length == 0 ) { 
                            if( onComplete != null ){ onComplete.apply(null,onCompleteParams) }
                            remove();
                            return;
                        }
                        currentLoops = _loops;
                        _currentLoop = currentLoops[0];
                    }
                    do{
                        if ( _limit < getTimer() - time ) { break all; }
                        var cont:Boolean = _currentLoop.func.apply( null, _currentLoop.params );
                    }while ( cont && _added == false)
                    if( cont != true ){
                        currentLoops.reverse(); currentLoops.pop(); currentLoops.reverse();
                    }
                    if ( _added ) {    _added = false; }
                    while( _currentLoop.loops.length == 0 ){
                        if( _currentLoop.onComplete != null ){ _currentLoop.onComplete() }
                        _currentLoop = _currentLoop.parent;
                        if( _currentLoop == null  ) { continue all; }
                    }
                    currentLoops = _currentLoop.loops;
                    _currentLoop = currentLoops[0];
                }
            }
        }
    }
    
     /**
     * LoopクラスはThreaderによって実行されるループ処理のクラスです。
     * @author shohei909
     */    
    class Loop extends Object{
        public var func:Function;
        public var params:Array;
        public var onComplete:Function;
        public var name:String;
        public var parent:Loop;
        public var loops:Vector.<Loop> = new Vector.<Loop>();
        function Loop( parent:Loop, func:Function, onComplete:Function = null, name:String = "" ){  
            this.func = func; this.onComplete = onComplete; this.parent = parent; this.name = name;
        }
    }
    /**
     * Threaderクラスはスレッドを実行するための静的なクラスです。
     * @author shohei909
     */
    class Threader extends Object{
        /** デフォルトの呼び出し間隔(ミリ秒)です。frameRateに合わせることで効率よく動作します。 */
        static public var defaultSpan:Number = 1000/60; 
        /** デフォルトの優先度です。 */
        static public var defaultRate:Number = 0.5;
        /** 全てのスレッドへの参照です。 */
        static public var threads:Vector.<Thread> = new Vector.<Thread>();
        
        /**
         * addThreadはThreaderの核となる関数です。
         * 
         * Threaderでは、loop関数を含むFunctionをaddThread関数を使って実行することで、マルチスレッドが開始されます。
         * 
         * @param    threadMethod スレッドとして実行する関数です。funcの
         * @param    params threadMethodに渡すパラメーターの配列です。
         * @param    threadParameters スレッドに設定するパラメーターです。
         * @return    追加されたスレッドです。
         * @see Thread
         * @see Thread#loop()
         */
        static public function addThread( threadMethod:Function, threadParameters:Object = null, params:Array = null ):Thread {
            var thread:Thread = new Thread();
            for( var str:String in threadParameters ){
                thread[str] = threadParameters[str];
            }
            if ( params == null ) {
                thread.loop( threadMethod ).params = [thread]
            }else{
                thread.loop( threadMethod ).params = [thread].concat( params );
            }
            return thread;
        }
        
        /**
         * 全てのスレッドを破棄します。
         */
        static public function removeAllThreads():void { 
            for each( var t:Thread in threads ) { t.remove(); }
        }
        
        /**
         * 現在進行中の全てのスレッドを一時停止します。
         */
        static public function pauseAllThreads():void { 
            for each( var t:Thread in threads ) { t.pause(); }
        }
        
        /**
         * 現在一時停止の全てのスレッドを再開します。
         */
        static public function resumeAllThreads():void { 
            for each( var t:Thread in threads ) { t.resume(); }
        }
        
        /**
         * 全てのスレッドを指定した時間(ミリ秒)だけ待機させます。
         */
        static public function sleepAllThreads( delay:int ):void { 
            for each( var t:Thread in threads ) { t.sleep( delay ); }
        }
        
        /**
         * nameが一致する、スレッドを破棄します。
         */
        static public function removeThreads( name:String ):void { 
            for each( var t:Thread in threads ) { if(t.name==name)t.remove(); }
        }
        
        /**
         * nameが一致する、現在進行中のスレッドを一時停止します。
         */
        static public function pauseThreads( name:String ):void { 
            for each( var t:Thread in threads ) { if(t.name==name)t.pause(); }
        }
        
        /**
         * nameが一致する、現在一時停止中のスレッドを再開します。
         */
        static public function resumeThreads( name:String ):void { 
            for each( var t:Thread in threads ) { if(t.name==name)t.resume(); }
        }
        
        /**
         * nameが一致する、スレッドを指定した時間(ミリ秒)だけ待機させます。
         */
        static public function sleepThreads( name:String, delay:int ):void { 
            for each( var t:Thread in threads ) { if(t.name==name)t.sleep( delay ); }
        }
    }
    
    
//Threaderライブラリここまで==========================================================================================================