Nokia Maps API Reference

Contents

Class nokia.maps.util.Coroutine

Class Summary

There are many different ways to run code in a non-blocking way. The most common is to use threads which are parallel execution paths. Threads can be cooperative or preemptive. In a cooperative threading design, each thread or process is in full control of the CPU and must explicitly release the CPU so that another thread or process can take control of the CPU. In preemptive threading, a scheduler takes away the CPU from a thread and allocates it to another thread, therefore the thread has little or no control over when it is runs and on which CPU.

Preemptive versus cooperative threading

Each of the two threading models has certain advantages and disadvantages. Cooperative threading is much simpler for developers, because access control is not required. It guarantees that the memory (and so variables) and all other resources are only accessed by the currently executing code. It is not possible for one instruction to modify a variable, while another tries to read it or (worse) modify it too, therefore it impossible to access a value that is in a "half updated" state. This means that in cooperative threading there is no need for mutexes to synchronize access to memory (variables). Another advantage is performance. Because no synchronization is required, cooperative threading can be implemented more simply and a thread switch is much cheaper then in a preemptive environment.

However, the disadvantage of cooperative threading is that each process can only use one processor, because otherwise mutexes would become necessary, as each variable could be modified by one thread, while another is reading it (or even worse, both could be modifying the same object at the same time, possibly leaving the object in an unusable state). Therefore true parallel execution within one process is not possible. The other disadvantage is that a bug in the code may block the application, making it unresponsive. In extreme cases, it may block the entire operating system, making it unresponsive, because the thread executing the faulty code does not release the CPU.

JavaScript execution

All JavaScript code is executed in an execution context. Whenever some JavaScript code is executed, a new execution context is created. An execution context is an abstract collection that contains an activation and a variable object (as well internal information). These objects contain all the arguments supplied to a function and all the variables declared within the code, using the var statement. Because in reality the activation and variable objects are the same object, we simply use the term variable object to refer to both of them from here on. If an argument is named, its value is referenced in the variable object using that name; if a named argument is not supplied, a variable with the name of the argument exists in the variable object, but has the value undefined (the variable declared, but its value is undefined). This is important, because assigning a value to it does not lead to pollution of the global scope.

The scope chain

For any JavaScript code to be executed, there must be a global execution context in which this code can be run. In a browser environment, the browser creates such a global execution context and fills the variable object of that global context with some default values, for example it sets document, navigator or Math. The variable object in this global context contains a reference to the global context (window), which is helpful in modifying the global scope. So every browser window has its own global execution context, where the variable object of the global context can be accessed via the window variable.

To resolve a variable name to a value, the JavaScript interpreter needs to look up the variable name in the so-called scope chain. A newly created function "remembers" the current execution context. Every time the function is called, the interpreter creates a new execution context and assigns the previous execution context as the parent of the new context, thus building the scope chain. If the JavaScript interpreter has to resolve a variable named "foo", it first searches in the variable object of the current execution context, which is the local context for the function. If no variable with that name is found there, the interpreter searches the parent execution context, then its parent, and so on, going up the chain until it reaches the global execution context (which has no parent). In short, the scope chain of a function is established at function create time and each subsequent call to the function adds a new element to that chain.

This is different for the eval statement, because eval executes the code that is passed to it in the current execution context. Therefore a variable declared within an eval statement with the var keyword extends the current execution context.

The following example shows the impact of this:

	// Create new variables within the variable object
	// of the current execution context.
	//
	var x = 1;
	var y = 99;

	// Create a new function -- it remembers the current execution 
	// context as its scope chain. The code is discussed below.
	//
	var alertX = function () {
		alert("x: "+x+", y: "+y);
		var y;
	};

	// Calling the function creates a new execution context with
	// a new variable object, the parent execution context of this new
	// execution context is set to the execution context that was
	// remembered at the create time of the function.
	//
	// The interesting thing at this point is the output:
	//
	//	 "x: 1, y: undefined"
	//
	// The reason is that the new execution context contains a variable 
	// declaration for "y", but no value is assigned to it, while 
	// the only definition for "x" is in the parent context, and "x" is
	// assigned a value there. 
	//
	alertX();

	// eval() is slow and should be avoided. The
	// interpreter must evaluate the code passed to eval() 
	// within the current execution context, so the declaration of the 
	// variable "x" in that code has no effect, because "x" is already 
	// declared in the variable object of the previous execution context.
	// Assigning 2 to "x" now modifies the "x" in the current execution
	// context, therefore the following code causes alert() 
	// to display "2" twice.
	//
	eval("var x = 2; alert(x);");
	alert(x);

	// The following example demonstrates that the execution context is remembered
	// at function create time. The example creates an anonymous function,
	// remembers the current execution context and then directly calls
	// the new function. The function call causes a new execution context to be
	// created with the parent execution context set to the current
	// execution context (note that create and call time of the function are
	// the same now).
	//
	(function () {
		// The code below causes the variable with the name "x" to be declared
		// in the variable object of the current execution context. Therefore
		// the variable of parent context with the same name is no longer
		// accessible from within the function.
		//
		var x = 3;

		// However, the call to the function alertX() below, creates a new execution
		// context with a new variable object, and assigns as the parent execution
		// context the execution context current at the time of the call. The code 
		// within alertX() cannot find a variable with the name "x" in its own variable 
		// object. It then searches its parent execution context (not the current 
		// execution context, where it would find "x" set to 3). In the parent context, 
		// "x" has the value of 2. Thus, the following line outputs "2" and not "3":
		//
		alertX();

		// Below, we create a new function. It is created there and then, therefore it
		// remembers the current execution context. Note that it contains the same
		// code that the alertX() function.
		//
		var fn = function () {
			alert("x: "+x+", y: "+y);
			var y;
		};

		// So when we call this function, a new execution context is created
		// and the execution context remembered at the create time of the function
		// is assigned as the parent execution context. Because the create time
		// of this function is just one line above, it is the current execution
		// context. So the interpreter searches for "x" in the variable object
		// of the new execution context, not fails to find it and then searches the parent
		// execution context, which is the current execution context that contains
		// a variable with the name "x" and the value "3". Therefore this
		// time, the output is "3" and not "2".
		//
		fn();
	})();

Threading

The above-described scope chain explains why every execution context is bound to exactly one thread and every execution context must be bound to the thread to which its parent execution context is bound. For this reason, multi-threading is not possible in JavaScript and this is also why web-workers (the threads of HTML 5) do not have access to variables of the current window or to the DOM tree of the Web page. Every web-worker has its own global execution context and the execution context of a web-worker does not contain a reference to any window. That is also the reason why web-workers can only communicate using strings. Strings are immutable (read-only) and therefore there is no need to synchronize access to strings.

Most browsers use the same thread to render the UI, to parse the DOM tree and to execute JavaScript. Therefore as long as JavaScript is executed, no rendering of the UI or Web pages occurs, but note that this does not apply to all browsers. In any case, a buggy JavaScript code may block the browser and therefore all browser vendors implement some way to detect if JavaScript is blocking to prevent the browser becoming unresponsive to the user. For example, the Internet Explorer stops processing JavaScript after a certain number of instructions have been processed (by default around 5 million) and informs the user that a script is making the browser unresponsive, asking the user to continue the script or to abort it. Other browsers, for example Firefox, make the message conditional on elapsed execution time rather than a number of instructions.

Why you should use a coroutine and not setTimeout()

It can happen (and within this API it happens often) that some code must run for a number of seconds and/or more than 5 million instructions must be executed to perform a specific action. This happens, for example in map rendering to process huge polylines or a large number of polylines/polygons. Even though this does not always force an alert box of the browser to pop up, it makes the browser slow and unresponsive to the user input for as long as the JavaScript code runs. This situation may last a second or longer and it may occur multiple times in a row. Note that the performance of a browser is heavily dependent on the device on which the browser is running. Browsers do not have any built-in support for these cases, the function setTimeout() by itself does not help, because it does not take into account which function consumes how much processor time and so does not help the developer keep the browser responsive. It is possible to implement a function with a mechanism that prevents the browser becoming unresponsive, but problems are likely to arise if two or more such function run concurrently without any knowledge of one another. This API offers the nokia.maps.util.Coroutine class as a safe solution.

Support for coroutines

As a user of this API you can create your own coroutines. The API implements a scheduler (nokia.maps.util.Coroutine.scheduler) which keeps track of how much CPU time each coroutine consumes, ensuring that 80% of the available CPU time (so of the time not consumed by other JavaScript libraries) is distributed to all running coroutines, leaving approximately 20% of the free CPU time to the browser itself for rendering and event processing. The API assists the developer in writing coroutines by offering functions that help coroutines release CPU at the right moment and the API helps in saving or restoring the state of a coroutine. However, that still leaves some work to be done by the developer of a coroutine.

Scheduler details

The scheduler ensures that each coroutine receives time to execute without consuming all available CPU time, so that there is enough time left for the browser to render the Web page(s), the UI and to process user input and to execute other JavaScript code. The scheduler implements the above-described design in software. Therefore the scheduler contains a global execution context. Whenever a new coroutine is created, the current execution context is "remembered" with the coroutine, and whenever a coroutine is called, a new execution context is created and its parent execution context it set to the execution context "remembered" with the coroutine at create time. The scheduler itself supports automatic priority management. So coroutines consuming a lot of CPU time are degraded while those not consuming any CPU time are upgraded. This ensures that coroutines consuming only a small amount of CPU time (for example those handling user input processing) are not delayed by coroutines consuming large amounts of CPU time (for example rendering jobs). The major advantage of the coroutines can be seen on mobile devices which have much less CPU power then desktop PCs.

Introduction to coroutines

Not every function can become a coroutine and a coroutine is not a normal function. As already mentioned, coroutines are cooperative, therefore there is no need for mutexes. A coroutine appears as if it were executed directly when it is called. A coroutine has to call the method shallYield() from time to time to check if it is time to release the CPU. If the shallYield() returns true, the coroutine must call the method yield() and return to the caller. Calling yield() signals the scheduler that the function is not finished, but wants to give way to some other code. Some time later, the scheduler calls the coroutine again to allow it to continue its work.

Because of this, coroutines must remember their state and execution position between calls. A coroutine can store variables including information about the current point of execution with the variable object. Additionally, it is possible for one coroutine to call another coroutine and then wait for the called coroutine to finish (otherwise both coroutines would execute in parallel). Note that it is also possible that a coroutine may not end at all, so that it is executed in an endless loop, for example, rendering functions do not stop unless the nokia.maps.map.Display class to which they belong is destroyed; instead, they just go to sleep if there is nothing for them to do.

The possible states of the execution context of a coroutine are:

  • terminated - the coroutine is finished
  • running - the coroutine is currently running, but this execution context is not necessarily being executed; multiple execution contexts can be marked as "running", but in fact, they can only run one after another in succession (see nokia.maps.util.Coroutine.current)
  • blocking - the coroutine is waiting for something, either waiting for a coroutine it has called or just sleeping for a moment

Simple coroutine examples

The following example shows a very simple coroutine that increments a counter and another coroutine that updates a div-tag with the current value of the counter:

	// A shortcut for easier access to the coroutine class:
	//
	var Coroutine = nokia.maps.util.Coroutine;


	// Create a new coroutine with the name "counter". It receives two 
	// arguments, the variable object and the execution context.
	//
	var counterCo = Coroutine.create("counterCo", function (scope, context) {
		// The following check is important, because if the parent
		// context contains a variable "counter" a simple check for
		// scope.counter would return true (scope chain) and then
		// using the counter of the parent context might lead to 
		// errors.
		//
		if (!scope.has("counter")) scope.counter = 0;

		// Loop until counter reaches 1 million.
		//
		while (scope.counter < 1*1000*1000) {
			// Increment the counter.
			//
			scope.counter++;

			// If we shall yield now, do that.
			//
			if (Coroutine.shallYield()) return Coroutine.yield();
		}
	});

	// Now let's run an instance of the coroutine.
	//
	var counterCoCtx = counterCo();

	// Create another coroutine to be used as render coroutine. This method
	// receives as the first argument a reference to the counter coroutine
	// execution context it is to track and to the div-tag into which the state
	// of the counter is to be rendered.
	var renderCo = Coroutine.create("renderCo", function (scope, context) {
		while (true) {
			// Output the current counter by accessing the variable
			// object of the counter coroutine and reading the value.
			//
			scope.div.innerHTML = "Current count is "+scope.counterCoCtx.scope.counter;

			// If the counter context is terminated, we terminate too.
			//
			if (scope.counterCoCtx.status === Coroutine.TERMINATED) break;

			// Otherwise put this coroutine to sleep for 10ms and then return.
			return Coroutine.sleep(10);
		};
	},
	// "counterCoCtx" is bound to the first parameter of the coroutine,
	// the variable "div" to the second parameter.
	//
	"counterCoCtx", "div");

	// Call the rendering coroutine for two different div-tags, but
	// the same counter.
	//
	var renderAContext = renderCo(counterCoCtx, document.getElementById("outputA"));
	var renderBContext = renderCo(counterCoCtx, document.getElementById("outputB"));

This was a very simple example of how to write coroutines. The whole concept becomes much more complex if one coroutine needs to invoke another coroutine or if it is necessary to wait until a coroutine has calculated a return value. As you can see, each coroutine receives the reference to the variable object. This does not mean that it is not possible to use local variables, but it should be taken into account that the state of the real local variables cannot be saved between two calls to a coroutine and therefore they must be used with caution.

Complex coroutines

The example below shows a much more complex coroutine, where one coroutine calls another and waits until the called coroutine is finished before using the return value from the called coroutine.

	// A shortcut to access the static coroutine class more easily.
	//
	var Coroutine = nokia.maps.util.Coroutine;

	// Create a function that adds all numbers from "from" to "to" and returns
	// the sum (and yes, we are aware that there are better ways to do it).
	//
	var addFromToCo = Coroutine.create("addFromToCo", function (scope) {
		// If the "sum" variable is not yet defined, initialize it with 0.
		//
		if (!scope.has("sum")) scope.sum = 0;

		// Loop until we've added all values.
		while (scope.from <= scope.to) {
			// Add the value of "from" to our "sum".
			//
			scope.sum += scope.from++;

			// If we are to release the CPU, do it.
			if (Coroutine.shallYield()) return Coroutine.yield();
		}

		// If we're finished, return the calculated sum.
		return scope.sum;
	}, "from", "to");

	// Create another coroutine to add a number from "a" to "b" "n" times.
	//
	var addMultiCo = Coroutine.create("addMultiCo", function (scope) {
		// In this case, everything gets a bit more complicated and we
		// have not only to remember some state variables, but also
		// the current execution point of the method (which we call "ip" 
		// -- short for "instruction pointer") when the function is 
		// called for the first time

		// When the method is called for the first time, the variable "sum" 
		// contains the calculated sum, "i" contains the counter to count to 
		// "n", and "addFromToCo" is a reference to an instance of the coroutine 
		// that calculates the sum from "a" to "b".
		//
		if (!scope.has("ip")) {
			scope.sum = 0;
			scope.i = 0;
			scope.ip = 1;
		}

		// Now let's run a loop from "i" to "n".
		//
		while (scope.i < scope.n) {
			// If the current instruction pointer is 1, we have to call
			// the "addFromTo" coroutine now
			//
			if (scope.ip===1) {
				// and then the instruction pointer is 2.
				//
				scope.addFromToCtx = addFromToCo(scope.a, scope.b);
				scope.ip = 2;
			}

			// If the instruction pointer is currently 2
			//
			if (scope.ip===2) {
				// but the "addFromTo" coroutine is not yet finished
				//
				if (scope.addFromToCtx.status !== Coroutine.TERMINATED) {
					// We have to wait until the "addFromTo" coroutine
					// has finished processing. Therefore the "wait" call
					// lets us wait until the coroutine fires a
					// notify or broadcast to all blocking coroutines,
					// which automatically happens if the coroutine is
					// terminated for whatever reason.
					//
					return Coroutine.wait(scope.addFromToCtx);
				}

				// If we've reached this point the coroutine "addFromTo" has
				// been called and is finished, therefore we can read the returned
				// value (which is a sum) and add it to the sum variable.
				//
				scope.sum += scope.addFromToCtx.returnValue;

				// Now let's increase the loop counter and reset the instruction
				// pointer to 1, so that the "addFromTo" coroutine is called
				// again in the next loop iteration.
				scope.i++;
				scope.ip = 1;
			}
		}

		// If we reach this point, the variable "i" has reached "n" and we're
		// finished, so let's return the calculated sum.
		//
		return scope.sum;
	}, "a", "b", "n");

	// Let's call the "addMulti" coroutine to add the numbers from 1 to 1000 and
	// this 1000 times. Wait until the coroutine is finished by registering an
	// observer for the "status" property of the execution context.
	//
	addMultiCo(1, 1000, 1000).addObserver(
		"returnValue",
		function (context, key, value, oldValue) {
			alert(context.returnValue);
		}
	);

This example should make one thing clear: It is very easy to use coroutines for a normal user, that is at application level, but it is much harder to write them. The user just needs to call the coroutine like a normal function, except he is interested in the return value. To obtain it, he calls the method and registers an observer for the "returnValue" property, waiting until the method is finished so that he can then process the return value asynchronously.

Extends Function.
ExecutionContext This class represents the execution context of a coroutine.
Scope Scope is an abstract class designed to hold variables available within the scope of a coroutine.
Method Summary
static all () : nokia.maps.util.Coroutine.ExecutionContext[] This method returns an array with all the execution contexts currently marked as "running" or "blocking".
static broadcast (obj) This method signals all coroutines blocking on an object and resumes them.
static catchException (enable) This method enables exception catching in the scheduler to ignore errors in coroutines or it can be used to disable exception catching for debugging purposes.
static count () : Number This method retrieves the number of contexts not being terminated, thus the return value includes all running and blocked contexts.
static create (name, fn) : Function This method creates a new coroutine, using the name and implementation supplied by the caller.
static createEx (name, fn, [defaults]) : Function This method creates a new coroutine using the name and implementation supplied by the caller.
static current () : nokia.maps.util.Coroutine.ExecutionContext This method returns the currently executed context or null if no context is executed right now.
static forId (id) : nokia.maps.util.Coroutine.ExecutionContext This method retrieves the execution context with the given id or undefined if no such context exists.
static forName (name) : nokia.maps.util.Coroutine.ExecutionContext[] This method searches through the list of all contexts currently in the "running" or "blocking" state and returns all those that are bound to the coroutine with the name supplied by the caller.
static kill ([context, [reason]]) : Object This method immediately terminates the currently executed coroutine or the supplied coroutine context.
static killAll () This method destroys all execution contexts currently in the "running" or "blocking" state.
static resume (context) This method resumes the supplied executed execution context.
static scheduler ([isTestUnitCall]) This method forces the scheduler to run at once.
static schedulerCpuTime () : Number This method retrieves the total CPU time that the scheduler itself has consumed.
static schedulerNextRuntime () : Number This method retrieves the UNIX timestamp showing when the scheduler should run again.
static scope (fn) This method clones the given function and moves the clone into the internal scope of the coroutine scheduler, removing the original scope remembered by the function.
static shallYield () : Boolean This method checks if the currently executed coroutine context must yield or not.
static signal (obj) : nokia.maps.util.Coroutine.ExecutionContext This method signals the given object and resumes the next coroutine that is blocked on this object, if any.
static sleep ([timeout, [context]]) : Object This method puts a coroutine context to sleep.
static suspend ([context, [timeout]]) : Object The method suspends the supplied execution context or the currently executed context.
static taskCpuTime () : Number This method retrieves the total CPU time that all contexts have consumed.
static totalCpuTime () : Number This method retrieves the number of milliseconds since the scheduler was started.
static wait (obj, [timeout, [context]]) : Object This method blocks the a coroutine on the object provided by the caller.
static yield (context) : Object This method makes the currently executed coroutine or the supplied one yield.
Field Summary
static Number AF_MAX_EXEC_TIME This property holds the maximal execution time for those coroutine being executed within the animation frame request (see nokia.maps.util.Coroutine.ExecutionContext#useAnimationFrame and nokia.maps.util.Coroutine#MAX_EXEC_TIME for details.
static Number AF_SLICE_SIZE This property holds the maximal size of each time slice for a coroutine being executed within the animation frame request (see nokia.maps.util.Coroutine.ExecutionContext#useAnimationFrame and nokia.maps.util.Coroutine#SLICE_SIZE for details.
static Object BLOCKED This property holds a special object returned by the sleep(), wait() and suspend() methods.
static Number BLOCKING Coroutine status constant indicating that a context is blocked at a condition or sleeping.
static Object KILLED This property holds a special object returned by the kill() method.
static Number MAX_EXEC_TIME This property holds the maximum execution time or the number of milliseconds consumed by coroutines before control is handed over to the browser and so to other JavaScript code.
static Number MIN_IDLE_TIME This property holds minimum time in milliseconds to leave to the browser for rendering and for processing events.
static Number RUNNING Coroutine status constant indicating that a context is currently running.
static Number SLICE_SIZE This property holds the maximum size of each time slice for a coroutine.
static Number TERMINATED Coroutine status constant indicating that a context is terminated.
static Object YIELDED This property holds a special object returned by the yield() method.
Direct Inheritance
Method Detail
This method returns an array with all the execution contexts currently marked as "running" or "blocking".
Returns:
{nokia.maps.util.Coroutine.ExecutionContext[]} An array with all execution contexts in the state "running" or "blocking", the array may be empty if no context is currently executed
static broadcast (obj)
This method signals all coroutines blocking on an object and resumes them.
Examples:
	var Coroutine = nokia.maps.util.Coroutine,
		condition = {},
		myCo = Coroutine.create("myCo", function (scope, context) {
			// If this is the first run ...
				if (!scope.ip) {
					// ... block on the condition.
					scope.ip = 1;

					return Coroutine.wait(condition);
				}
				alert("coroutine "+ context.name+" is now awake!");
				// coroutine terminates here.
		});

	// Call the coroutine twice.
	myCo();
	myCo();

	// After two seconds, wake all waiting coroutines.
	setTimeout(function () {
		Coroutine.broadcast(condition);
	}, 2000);
Parameters:
{Object} obj The object on which to resume all blocking coroutines.
static catchException (enable)
This method enables exception catching in the scheduler to ignore errors in coroutines or it can be used to disable exception catching for debugging purposes. By default, exceptions are caught and written into the debug console.
Parameters:
{Boolean} enable true enables exception catching, false disables it
static count () : Number
This method retrieves the number of contexts not being terminated, thus the return value includes all running and blocked contexts.
Returns:
{Number} The number of contexts that are not terminated
static create (name, fn) : Function
This method creates a new coroutine, using the name and implementation supplied by the caller.
Parameters:
{String} name The name of the coroutine
{Function} fn The function that implements the coroutine
{String} [args...]: An unlimited number of strings with the names of the arguments of this function
Returns:
{Function} The coroutine with the supplied function as internal run-function
See:
nokia.maps.util.Coroutine
static createEx (name, fn, [defaults]) : Function
This method creates a new coroutine using the name and implementation supplied by the caller. It creates coroutine by nokia.maps.util.Coroutine.create call and links defaults to the coroutine context.
Parameters:
{String} name The name of the coroutine
{Function} fn The function that implements the coroutine
{Object} [defaults]: A hashmap with default values for all created contexts, currently the only options being supported are priority and useAnimationFrame
{String} [args...]: An unlimited amount of strings with the names of the arguments of this function
Returns:
{Function} The coroutine with the supplied function as internal run-function
See:
nokia.maps.util.Coroutine
This method returns the currently executed context or null if no context is executed right now.
Returns:
{nokia.maps.util.Coroutine.ExecutionContext} The currently executed context or null if no context is executed
This method retrieves the execution context with the given id or undefined if no such context exists.
Parameters:
{String} id The unique execution context id for which to search
Returns:
{nokia.maps.util.Coroutine.ExecutionContext} The execution context with the given unique id or undefined if no context with that id exists
static forName (name) : nokia.maps.util.Coroutine.ExecutionContext[]
This method searches through the list of all contexts currently in the "running" or "blocking" state and returns all those that are bound to the coroutine with the name supplied by the caller.
Parameters:
{RegExp | String} name The name of the coroutine to find or the regular expression to match against the coroutine name
Returns:
{nokia.maps.util.Coroutine.ExecutionContext[]} An array with all contexts where the matching name was found or an empty array if no coroutine matches
static kill ([context, [reason]]) : Object
This method immediately terminates the currently executed coroutine or the supplied coroutine context.
Parameters:
{nokia.maps.util.Coroutine.ExecutionContext} [context]: The coroutine context to terminate; if not provided, the currently executed coroutine context is terminated, if executed
{Object} [reason]: Reason for termination, if any; if the first argument is omitted, the second argument becomes the first and must not be an instance of nokia.maps.util.Coroutine.ExecutionContext.
Returns:
{Object} If the context is killed, the method returns a nokia.maps.util.Coroutine.KILL object, otherwise undefined
static killAll ()
This method destroys all execution contexts currently in the "running" or "blocking" state.

The method is intended for debugging purposes or to be used when the user has left a Web site and resources are to be freed.

static resume (context)
This method resumes the supplied executed execution context.

It unblocks the context from any condition on which it is currently blocked or wakes it up if it is sleeping. If it is a realtime context, the context becomes the next one to be executed, otherwise it is added at the end of the pending contexts.

Parameters:
{nokia.maps.util.Coroutine.ExecutionContext} context The execution context to resume
static scheduler ([isTestUnitCall])
This method forces the scheduler to run at once.

Note that you should avoid calling this method, except if you have a very specific reason to do so, because by calling the scheduler directly, you bypass the normal scheduling and therefore you can cause the coroutine switching to become jerky and the browser might become unresponsive.

Parameters:
{Boolean} [isTestUnitCall]: True if this is a test unit call, false otherwise (this parameter may only be used for internal test units).
static schedulerCpuTime () : Number
This method retrieves the total CPU time that the scheduler itself has consumed.

The returned value is not very precise, because some method calls are not be counted for the scheduler due to performance impact. If the context calls for example yield() or sleep(), this counts as context time, even though a small amount of that time normally should have be scheduler time.

Returns:
{Number} The number of milliseconds of CPU time the scheduler has consumed for itself
static schedulerNextRuntime () : Number
This method retrieves the UNIX timestamp showing when the scheduler should run again.

This together with the manual scheduler call can be used to work around browser bugs such as the bug in IE that causes it not to call any function registered using setTimeout or setInterval while the user drags with the left mouse button. To counteract this, for example, nokia.maps.dom.Page class implements a workaround that calls the scheduler within a mousemove or drag event if the current time is later then the scheduler's next run time.

Returns:
{Number} The UNIX timestamp showing when the scheduler should be executed again
static scope (fn)
This method clones the given function and moves the clone into the internal scope of the coroutine scheduler, removing the original scope remembered by the function.

This method is intended for debugging or hot-fixing purposes. It allows you to modify, read and replace internal methods and properties.

Parameters:
{Function} fn The function which is copied into the scope.
static shallYield () : Boolean
This method checks if the currently executed coroutine context must yield or not.
Returns:
{Boolean} true if the currently executed coroutine context is to yield; false otherwise
This method signals the given object and resumes the next coroutine that is blocked on this object, if any.
Examples:
	var Coroutine = nokia.maps.util.Coroutine,
		condition = {},
		myCo = Coroutine.create("myCo", function (scope, context) {
				// If this is the first run ...
			if (!scope.ip) {
				// ... block on the condition.
				scope.ip = 1;
				return Coroutine.wait(condition);
			}
			alert("coroutine is now awake!");
			// coroutine terminates here.
		});
	// Call the coroutine.
	myCo();
	// In 2 seconds wake the coroutine up.
	setTimeout(function () {
		Coroutine.signal(condition);
	}, 2000);
Parameters:
{Object} obj The object on which to signal the next blocking coroutine
Returns:
{nokia.maps.util.Coroutine.ExecutionContext} Either the context that has been unblocked or undefined if no coroutine was blocking on this object
static sleep ([timeout, [context]]) : Object
This method puts a coroutine context to sleep.
Examples:
		// Always use a "return" when calling Coroutine.sleep() to break the current execution.
		return Coroutine.sleep(10000, myCoCtx);
Parameters:
{Number} [timeout]: The number of milliseconds the coroutine context is to sleep; if omitted, the coroutine sleeps until resumed or terminated
{nokia.maps.util.Coroutine.ExecutionContext} [context]: The execution context to put to sleep; if not given, the currently executed execution context is used, if any
Returns:
{Object} If the context is blocked, the method returns the nokia.maps.util.Coroutine.BLOCKED object, otherwise undefined
static suspend ([context, [timeout]]) : Object
The method suspends the supplied execution context or the currently executed context.
Examples:
		// Always use a "return" when calling Coroutine.suspend() to break the current execution.
		return Coroutine.suspend(myCoCtx);
Parameters:
{nokia.maps.util.Coroutine.ExecutionContext} [context]: The execution context that to suspend; if omitted or null/undefined, the currently executed context is suspended, if any
{Number} [timeout]: The maximum amount of time to block in milliseconds; if null or undefined, the method blocks until the coroutine is notified, resumed or terminated
Returns:
{Object} If the context is blocked, the method returns the nokia.maps.util.Coroutine.BLOCKED object, otherwise undefined
static taskCpuTime () : Number
This method retrieves the total CPU time that all contexts have consumed.
Returns:
{Number} The number of milliseconds of CPU time all contexts have consumed together
static totalCpuTime () : Number
This method retrieves the number of milliseconds since the scheduler was started.
Returns:
{Number} The number of milliseconds since the scheduler was started
static wait (obj, [timeout, [context]]) : Object
This method blocks the a coroutine on the object provided by the caller.

Note that the object gets a new property called "$blocking" which is managed by the coroutine manager and must not be modified.

Examples:
	var Coroutine = nokia.maps.util.Coroutine,
		condition = {},
		myCo = Coroutine.create("myCo", function (scope, context) {
			// If this is the first run ...
			if (!scope.ip) {
				// ... block on the condition.
				scope.ip = 1;
				// Using a "return" when calling Coroutine.yield() we break the current execution
				return Coroutine.wait(condition);
			}
			alert("coroutine is now awake!");
			// coroutine terminates here.
		});
	// Call the coroutine.
	myCo();
	// Wake up the coroutine in two seconds.
	setTimeout(function () {
		Coroutine.signal(condition);
	}, 2000);
Parameters:
{Object} obj The object on which the coroutine is to be blocked
{Number} [timeout]: If provided, this argument is the maximum length of time in milliseconds that the coroutine blocks, otherwise if the argument is null or undefined, the method blocks for ever
{nokia.maps.util.Coroutine.ExecutionContext} [context]: The execution context to block; if the argument is omitted, the currently executed context is used, if any is currently executed
Returns:
{Object} If the context is blocked, the method returns the nokia.maps.util.Coroutine.BLOCKED object; otherwise undefined
static yield (context) : Object
This method makes the currently executed coroutine or the supplied one yield.
Examples:
	var YIELD_EVERY = 64,
		yieldCount = 0,
		Coroutine = nokia.maps.util.Coroutine,
		myCo = Coroutine.create("myCo", function (scope, context) {
			console.log("yieldCount" + yieldCount);
			while (++yieldCount < 1000) {
				// Break the execution of the while loop, using the yield method.
				// Using a "return" when calling Coroutine.yield() we break the current execution.
				if (!(yieldCount % YIELD_EVERY)) return Coroutine.yield();
				
				// coroutine terminates here.
			}
		});
	myCo();
Parameters:
{nokia.maps.util.Coroutine.ExecutionContext} context The execution context of the coroutine to yield, if not given the currently executed context is suspended
Returns:
{Object} If the context is blocked the method returns the nokia.maps.util.Coroutine.YIELDED object, otherwise undefined
Field Detail
static Number AF_MAX_EXEC_TIME
This property holds the maximal execution time for those coroutine being executed within the animation frame request (see nokia.maps.util.Coroutine.ExecutionContext#useAnimationFrame and nokia.maps.util.Coroutine#MAX_EXEC_TIME for details.
static Number AF_SLICE_SIZE
This property holds the maximal size of each time slice for a coroutine being executed within the animation frame request (see nokia.maps.util.Coroutine.ExecutionContext#useAnimationFrame and nokia.maps.util.Coroutine#SLICE_SIZE for details.
static Object BLOCKED
This property holds a special object returned by the sleep(), wait() and suspend() methods.
static Number BLOCKING
Coroutine status constant indicating that a context is blocked at a condition or sleeping.
static Object KILLED
This property holds a special object returned by the kill() method.
static Number MAX_EXEC_TIME
This property holds the maximum execution time or the number of milliseconds consumed by coroutines before control is handed over to the browser and so to other JavaScript code.

The smaller this time slice becomes, the more often the browser regains control and the smoother the execution of coroutines, so the browser appears to be more responsive, but as more overhead is produced and finally as less CPU time is used for the API, so as slower the API execution.

static Number MIN_IDLE_TIME
This property holds minimum time in milliseconds to leave to the browser for rendering and for processing events.

The amount of CPU time left for the browser can be calculated by dividing the minimum idle time by the maximum execution time plus the minimum execution time. By default the value is 20%. Note that this is also the minimum amount of CPU time left for JavaScript code that is not part of the API. Increasing or decreasing this time might be necessary and can be done at runtime, depending on the situations, for example if you need a lot of CPU time for other libraries. This property is no longer supported.

static Number RUNNING
Coroutine status constant indicating that a context is currently running.
static Number SLICE_SIZE
This property holds the maximum size of each time slice for a coroutine.

This value determines how many coroutines can run per scheduled time period, so it decides how long it takes until a coroutine gets a slice of CPU time. If this value is too big and a large number of coroutines run simultaneously, it can take seconds until each coroutine gets some CPU time, so tasking becomes unsteady, but performance is improved as fewer coroutine switches occur. If this value is too small and a large number of coroutines run at simultaneously, each coroutine gets a slice of CPU time faster, but the slice is also smaller, so execution of coroutines may seem to smoother, but the amount of CPU time lost due to coroutine switching increases, so the overall performance decreases.

This value is normally exactly 25% of the maximum execution time and you should keep it around that value. However, if you decrease the maximum execution time below 50ms you should consider increasing this value to 100%, so the same value as the maximum execution time and if you increase the maximum execution time to above 300ms you should consider changing this value to 10% of the maximum execution time (e.g. 75 for 300).

static Number TERMINATED
Coroutine status constant indicating that a context is terminated.
static Object YIELDED
This property holds a special object returned by the yield() method.
Documentation generated on Wed Jun 27 2012 16:54:33 GMT+0200 (CEST).