Archive for the ‘ActionScript’ Category

Threading in Flex

There have been several times where we have had to process large sets of data in our client side Flex applications. Several of these locked the UI for up to 15 seconds on slower machines until we started chunking up the work load.

Eventually, we solved this issue by developing a framework to instantiate and manage ‘thread’ objects. The threads are really just managed time slices.

The framework has the following features:

* easily instantiate and manage n number of threads
* threads have adjustable priority settings
* messaging between threads handled by reflective method handlers (similar to Fabrication for PureMVC)
* load balancing of thread executions in order to optimize performance
* easy and simple api: start(), sleep(), wake(), kill()
* threads can auto-adjust their workload based on the performance of the application. basically, if the app is slowing down, the threads can buffer down their work load. similarly, they can ramp their workload up if the application is running smoothly and the library feels that there is room for increased load.

This library has gone through our open source review board and has been approved to be released into the wild ๐Ÿ™‚

You can get it here:
http://code.google.com/p/async-threading/

The project archive file contains src, asdoc, and compiled swc.

Advertisements

Playing with Tamarin

I played around with Tamarin about a month ago and have been meaning to blog about it. Tamarin is the Adobe/Mozilla open source ActionScript virtual machine. You can figure out how to install and build it here (I don’t want to go through all of the gory details).

Building a project is fairly simple. You use the asc.jar (ActionScript compiler) to create an abc file (action byte code? alphabet a-b-c?). Then you run it with the avmshell. The first thing I did is write this awesome piece of code:

print("hello worlds.")

Note that we get a “print” function. The Tamarin ActionScript language is the same as the Flash/Flex AS3 that we all are used to, but it’s platform is different so the packages are different. The print function dumps text out to the console.

In my Mac terminal (Windows should be similar if not the same), I type:

java -jar ./tamarin-central/utils/asc.jar -import 
   ./tamarin-central/core/builtin.abc hello.as

And it makes hello.abc (which clocks in at a whopping 87 bytes).

./tamarin-central/objdir-release/shell/avmshell hello.abc

Outputs: “hello worlds.”

I did some digging around in the tamarin-central/shell path and found shell-toplevel.as. This has all sorts of good stuff in it… a File class memory in and out. A readline function. Here’s the next little test I wrote:

import avmplus.File 

var foo:Array = ["hello", "world", "yo"];
var i:uint = 0; 

for ( i = 0; i < foo.length; i++ ) { 
    print( foo[i] ); 
} 

print( "writing to a hello2.txt..." ); 
File.write( "hello2.txt", foo.toString() ); 

print( "reading file..." ); 
try { 
    print( File.read('hello2.txt') ); 
} catch (e) { 
    print( e.toString() ); 
}

It outputs:

hello
world
yo
writing to a hello2.txt...
reading file...
hello,world,yo

And creates a “hello2.txt” along the way. Sweeet.

Now I just have to figure out what this is all useful for. ๐Ÿ™‚

uint and int reflection crazyness

I was writing some unit tests for a Flash-C++ integration and noticed some quirky behavior with number reflection. getQualifiedClassName() and describeType() always return “int” for a “uint”. Also, if an integer is used in a Number type it will call it an “int”.

For example,

var foo:Number = 42;
trace( getQualifiedClassName( foo ) );

That ouputs “int” not “Number”. Then if I gofoo += .02 it suddenly realizes that it is a Number. Whether this is Flash sneakily trying to save RAM or this is a bug, I dunno. I do know that it is weird.

Cairngorm Observable Front Controller (part 2)

(See part 1 here.)

So I was thinking about how we can better test our applications using automation. I know there are complex and great tools out there to do this– specifically ones that use the mx.automation package, but I wanted to play around and make my own.

Recording Cairngorm Events

The first thing we need to do is import a bunch of stuff. I’ll get into what they do later…

import flash.utils.getDefinitionByName; 
import flash.utils.getQualifiedClassName; 
import mx.rpc.xml.SimpleXMLDecoder; 
import mx.rpc.xml.SimpleXMLEncoder; 
import flash.xml.XMLDocument; 
import flash.xml.XMLNode; 

Then we hook onto that event from last time

eventDispatcher.addEventListener( ExecuteCommandEvent.EXECUTED, eventFired );

And we’ll want a variable to hold the session. I have to use the old-skool XMLDocument because I’m using the SimpleXMLEncoder to encode the Cairngorm Event into XML.

private var _testScriptXML = new XMLDocument( "<script></script>" );

Now let’s encode it:

private function eventFired( event:ExecuteCommandEvent ):void {
    var simpleXMLEncoder:SimpleXMLEncoder = new SimpleXMLEncoder( _testScriptXML );
    var xmlNode:XMLNode = simpleXMLEncoder.encodeValue( event.cairngormEvent, 
new QName("cairngormEvent"), _testScriptXML.firstChild );
             
    xmlNode.attributes["class"] = getQualifiedClassName( event.cairngormEvent );
    xmlNode.attributes["type"] = event.cairngormEvent.type;
    xmlNode.attributes["bubbles"] = event.cairngormEvent.bubbles.toString();
    xmlNode.attributes["cancelable"] = event.cairngormEvent.cancelable.toString();        
}

The encoding is straight-forward, although a bit painful because we have to deal with XMLDocument instead of XML. Sigh…. Also at this point you could output the recording to a text area.

Playback

Okay. Recording is nice and all, but pretty useless. Let’s roll it back out now.

private var _testCurrentNode:XMLNode; 
private var _testPlaybackInterval:Number;

The _testCurrentNode will be the current XML Node representation of the event that we are playing. _testPlaybackInterval will be used for setInterval.

So now we add a function that takes a string version of our script, turns it into XML (old-skool style) and starts the playback.

public function startTestHarnessForPlayback( scriptToPlay:String ):void {
    _testScriptXML = new XMLDocument( scriptToPlay ); 
    _testCurrentNode = _testScriptXML.firstChild.firstChild; 
    _testPlaybackInterval = setInterval( fireNextEvent, 1000 ); 
}

Firing the event gets a little more complicated. After decoding it we have to create the Class from a string using getDefinitionByName(). This method let’s us give it a string name of a class (like “foo.animal.Cat”) and it will create that Class (with a capital C). We then have to create an instance from the Class and populate it.

private function fireNextEvent():void {
    trace("~" + _testCurrentNode.toString() ); 

    // decode the XML into an Object             
    var simpleXMLDecoder:SimpleXMLDecoder = new SimpleXMLDecoder();
    var decodedObj:Object = simpleXMLDecoder.decodeXML( _testCurrentNode );

    // create a new Cairngorm Event from the object 
    var eventClass:Class = getDefinitionByName( _testCurrentNode.attributes["class"] ) as Class;
    var event:CairngormEvent = new eventClass( _testCurrentNode.attributes["type"], _testCurrentNode.attributes["bubbles"] == "true", _testCurrentNode.attributes["cancelable"] == "true" );
     
    // populate the Cairngorm Event 
    for ( var key:String in decodedObj ) {
        if ( _testCurrentNode.attributes[ key ] == undefined ) { 
            event[ key ] =decodedObj[ key ]; 
        } 
    } 

    // dispatch it         
    event.dispatch(); 

    // move on, unless we're done 
    _testCurrentNode = _testCurrentNode.nextSibling; 
    if ( !_testCurrentNode ) { clearInterval( _testPlaybackInterval ); } 
}

Right on. So that will let you record and playback a Cairngorm application. I think if I was to take it a step further, I’d add pauses into the scripts and even event hooks that it waits for. Oh well. Maybe later.

Cairngorm Observable Front Controller (part 1)

One of the reasons I like Cairngorm is because it is small. Hence, the microย in micro-architecture.ย ย (There are things I don’t like about Cairngorm too, but I’ll save that for a different post). Anyway, it’s smallness makes it easy to understand and build on top of.

The Unobservable Front Controller

As-is the Front Controller simply adds listeners to the Cairngorm Event Dispatcher. These listeners fire the executeCommand function and that creates a new command and executes it. Under normal circumstances, that’s awesome and it’s probably good that it is contained the way it is. But what if you want to log what commands are fired? This might be a good way to do analytics reporting and prevent tight coupling with the app.

One way you could do this is by looping through the commands dictionary. But you’d have to know when all of the commands were done being added or removed.

Another strategy is to extend the Front Controller…

The Observable Front Controller

The ObservableFrontController code looks like this:

  1 package testLib { 
  2  
  3     import com.adobe.cairngorm.control.CairngormEvent;
  4     import com.adobe.cairngorm.control.FrontController;
  5     import flash.events.EventDispatcher; 
  6      
  7     public class ObservableFrontController extends FrontController
  8     { 
  9         public var eventDispatcher:EventDispatcher = new EventDispatcher();
 10          
 11         public function ObservableFrontController() {
 12             super(); 
 13         } 
 14          
 15  
 16         override protected function executeCommand( event:CairngormEvent ):void {
 17             // dispatch the event wrapped in an ExecuteCommandEvent
 18             var executeEvent:ExecuteCommandEvent = new ExecuteCommandEvent();
 19             executeEvent.cairngormEvent = event;
 20             eventDispatcher.dispatchEvent( executeEvent ); 
 21              
 22             // move on 
 23             super.executeCommand( event );
 24         } 
 25          
 26     } 
 27 }

All it does is override executeCommand and repackage the event into a ExecuteCommandEvent. Here’s the ExecuteCommandEvent:

  1 package testLib 
  2 { 
  3     import com.adobe.cairngorm.control.CairngormEvent;
  4     import flash.events.Event; 
  5  
  6     public class ExecuteCommandEvent extends Event
  7     { 
  8          
  9         public static const EXECUTED:String = "executeCommandEvent";
 10          
 11         public var cairngormEvent:CairngormEvent;
 12          
 13         public function ExecuteCommandEvent() {
 14             super(EXECUTED, false, false);
 15         } 
 16          
 17     } 
 18 }

You with me? Not bad… yet. This sets it all up so I can add and a listener that will watch ANY command that the front controller fires. Next post I’ll talk about how you can make a simple automator tool that