AS3 programming 101 for C/C++ coders

In my previous article, I covered ActionScript 3 languange syntax and constructs that may be of interest to C/C++ coders starting out on ActionScript 3. This article covers areas of AS3 that are different from C/C++ in regards to functional issues that may be interesting to people with C/C++ experience. ActionScript 3 is a powerful language with some very nice features. However, as a long time C/C++ coder I found ActionScript lacking things I was used to having.

 

No control over application message loop

In a standard C/C++ application, your application has full control of the message loop. In Flash/ActionScript, this is not the case. The main application message loop is controlled by the application that is hosting the Flash player. This is either the browser, the stand alone flash player, or some other custom application. Flash is purely event driven. Your Flash application receives callbacks for every type of notification. This includes things like user events, application commands, and network responses. This means that ActionScript cannot block for any reason. If your Flash application blocks in a loop (or just just taking a long time computing something), the entire player and perhaps even the host application will block as well. Flash must handle everything via asynchronous callbacks.

In a typical desktop application written in C/C++, modal dialogs manage the message loop. This allows a modal dialog function to block and then return when the user is finished without causing the entire application to freeze. This is not the case in ActionScript. In ActionScript, you must display the modal dialog then return and wait for a callback that indicates what the user chose. This also means that using "alert" dialogs in ActionScript for debugging purposes is not entirely useful since the alert will display and the application will continue running.

Sho Kuwamoto from the Flex Builder team has a running series of articles covering the issues of "Dealing with asynchronous events". So far, he has Part 1, Part 2, and Part 3 available. I strongly recommend reading these articles. They provide a lot of good information for dealing with asynchronous nature of AS3.

 

No threads

In Flash/Flex, your application executes in a single thread. If you are used to using threads in your applications, this can feel somewhat constraining. However, since all AS3 applications are event driven and must handle everything asynchronously, AS3 has some nice language features that allows you to make asynchronous calls. Granted, asynchronous function calls are no where near a replacement for true threading, but asynchronous calls can provide for a similar user experience if you architect your application with this design pattern in mind.

The Timer class is very useful in this area. The Timer class allows you to schedule a function to be called by the framework at a later time on fixed intervals via "timer" event notifications. You can think of these timer events as time slices in which your asynchronous logic can execute. Since all Flash applications run in a single thread, you never need to worry about locking, mutexes, or semaphores, but you do need to be careful that any asynchronous function call does not take too long or the application will appear to hang or freeze.

 

No enum

AS3 has no enum. This can make porting C/C++ code to ActionScript a little more work. The lack of an enum may also disrupt how someone versed in C/C++ would approach a problem. Some people have come up with dynamic runtime solutions. For example, Darron Schall’s EnumeratedType class provides a single class that allows you to declare a new "enum" where ever needed. This is a nice, simple design that solves the runtime issues related to enums. It however does not catch errors at compile time (mismatched assignments or comparisons, etc.), because the AS3 language only has primative types for us to use which can accept any assignment.

Another approach could be as simple as defining a class with statics:

public class MyEnum{static public const FIRST:MyEnum = new MyEnum();static public const SECOND:MyEnum = new MyEnum();static public const THIRD:MyEnum = new MyEnum();}

This class then could be used similar to enum definitions when assigning or comparing variables as such:

public function getValue() : MyEnum{return MyEnum.SECOND;}

This way requires you to create a new file/class for each enum, but it enforces type safety because you are passing the data around as a custom type.

 

Public class constructors and singleton objects

In AS3, all class constructors must be public. This limitation is mainly due to the fact that ECMAscript 4 is not final and AS3 has chosen to abstain from protected/private constructors until it is resolved. But this limitation means is that AS3 does not have a straight forward way of implementing singleton classes. If the constructor must be public, anyone can create an instance of your class. However, there is a little trick you can use to implement a singleton class in AS3 that will ensure that is one and only one instance of your class.

In my previous AS3/C++ article, the section "Only one packaged class per file" touched on an interesting nuance of AS3 that allows you to declare a class outside the package declaration. This class is only accessable to code within that file. We can use this to create an implementation of a singleton class. The following code represents the contents of a file named “Singleton.as”:

package my.package{public class Singleton{public function Singleton(blocker:SingletonBlocker){if (blocker == null)throw new Error("Public construction not allowed.  Use getInstance()");}public static function getInstance() : Singleton{return instance;}private var instance:Singleton = new Singleton(new SingletonBlocker());}}// Outside the package, declare the blocker classclass SingletonBlocker{}

Since the “SingletonBlocker” class is outside the package declaration, other classes do not have access to it. The public constructor of the Singleton class requires the "blocker" parameter, otherwise it throws an exception. The combination of these two controls prevents any code from outside this file from ever constructing a new "Singleton" object instance. The only way to obtain a valid instance is to call the static function "getInstance()".