Search code examples
multithreadingactionscript-3flashair

Response from service as a callback is not concurrent in actionscript?


I am developing an AIR application for iOS/ Android and I am using a backend service for database operations. The backend service provides asynchronous API's for loading and saving the data. I happen to stumble at a piece of logic which caught my attention:

Main

public funciton loadPlayerData():void
{
    service.loadData();

    // Busy lock

    while( !service.client == true );

    // Do some stuff after the client is received
}

Service

public function loadData()
{
    // Call the external service and specify success callback as
    // onSuccess
}

public function onSuccess():void
{
    this.client  = true;
}

public var client:Boolean  = false;

What I am trying to do in the above code is that I am calling an async operation on service and while it is fetching data from server, I am busy spinning waiting for the client to set true in the callback. According to my understanding, this is how locking is done for resources in operating system and all. ( Though there are more elegant solutions in operating system other than busy wait ).

But the results are such that the Main gets stuck in an infinite busy waiting implying that onSuccess never gets called. The reason, according to my understanding is that until and unless the the current execution ends ( or when the stack of current execution is completely popped out), control is not given to the callback Function and hence my implementation results in never ending spin wheel. My basic assumption that thread is multiplexed from time point of view is flawed and thats the explanation I can deduce from the premise.

I want to know whats the actual reason behind the above scenario? How far I am correct in my deduction and what are the details behind execution of actionscript code in scenario like these ?


Solution

  • The AS3 runtime is not multithreaded - your script runs on a single thread with certain operations internally running on a separate thread (like network calls, etc.) The only way to properly handle your situation is to split up your work into multiple steps; you then initiate the first step (calling the remote service) and pass a callback function. There's no need to wait in a loop (in fact, it hurts you as you discovered) - when the network call is done, your callback will be called and you can initiate the next step of your processing. Until this 2nd step is called, the rest of your program should assume that the data from the remote service is not available.

    Your code would be something like:

    public funciton loadPlayerData():void
    {
        service.loadData();
    
        // Nothing else here - you must wait for the data
        // to be avaiable.
    }
    
    public function loadData()
    {
        // Call the external service and specify success callback as
        // onSuccess
    }
    
    public function onSuccess():void
    {
        // Call logic that performs "Do some stuff 
        // after the client is received" from your
        // question.
    }