Table of Contents

Overview

Sqrat Threading is a utility module for Squirrel that aims to provide new and useful capabilities to Sqrat's existing threading model.

Sqrat Threading is a standalone module intended for use with Sqrat Import. It has no dependancy on the Sqrat Binding library.

Functions

paramFunc schedule(threadFunc)

schedule creates a new thread and adds it to a simple round-robin scheduler. Scheduled threads run in the order they were added, rotating through the list as each thread yields it's execution. Scheduled tasks are executed by calling run.

	thread <- ::import("sqratthread", {});
	
	function funcA() {
		::print("Called A");
	}
	
	function funcB() {
		::print("Called A");
	}
	
	thread.schedule(funcA);
	thread.schedule(funcB);
	thread.run(); // Runs funcA, then funcB
	

When schedule is called a function is returned that takes the parameters to call the thread function with when it is run. Any number of parameters can be passed in this way.

	function threadPrint(arg) {
		::print(arg);
	}
	
	function printSum(a, b) {
		::print(a + b);
	}

	thread.schedule(threadPrint)("Hello");
	thread.schedule(threadPrint)("World");
	thread.schedule(printSum)(12, 30);
	thread.run();
	

Scheduled threads can be suspended just like any other thread, which will allow execution to proceed to the next scheduled thread. Once all threads have suspended or yielded execution the scheduler starts over on the first remaining thread, waking it up automatically and continuing execution. Threads that finish execution are removed from the scheduler.

	function firstRun() {
		::print("Start!");
	}
	
	function ping() {
		while(true) {
			::print("Ping...");
			::suspend();
		}
	}
	
	function pong() {
		while(true) {
			::print("Pong...");
			::suspend();
		}
	}

	thread.schedule(firstRun); // Will only run once
	thread.schedule(ping);
	thread.schedule(pong);
	thread.run(); // ping and pong will alternate forever.
	

Threads can be added to the scheduler while it is running too, which allows for an alternate version of the above code:

	function ping() {
		::print("Ping...");
		thread.schedule(pong);
	}
	
	function pong() {
		::print("Pong...");
		thread.schedule(ping);
	}

	thread.schedule(ping);
	thread.run(); // ping and pong will alternate forever.
	

run()

run executes any currently scheduled threads, blocking until the all scheduled threads have completed.

sleep(duration)

sleep will suspend the execution of a thread for at least the time span indicated by duration, which is provided in seconds as a float. In order for sleep to be effective the thread must be woken up at a regular interval, and therefore it is recommended that sleep is used in conjunction with schedule.

If a sleeping thread is woken up before the sleep duration is passed the thread will immediately suspend execution again. Calling sleep with a duration of 0 is synonymous with calling suspend directly.

	thread <- ::import("sqratthread", {});
	
	function countSeconds() {
		local i = 0;
		while(true) {
			::print(i + " seconds");
			i++;
			thread.sleep(1.0);
		}
	}
	
	function countFiveSeconds() {
		local i = 0;
		while(true) {
			::print(i + " is a multiple of 5!");
			i+=5;
			thread.sleep(5.0);
		}
	}
	
	thread.schedule(countSeconds);
	thread.schedule(countFiveSeconds);
	thread.run();
	

The expected output of the above script is every second a new "x seconds" message is printed, and every five seconds "x is a multiple of 5" is printed.

	1 seconds
	2 seconds
	3 seconds
	4 seconds
	5 seconds
	5 is a multiple of 5!
	6 seconds
	7 seconds
	8 seconds
	9 seconds
	10 seconds
	10 is a multiple of 5!
	...
	

thread getthread()

getthread returns the currently executing thread object. This function is primarily intended to allow threads to pass self references between themselves to facilitate easier dynamic wakeup logic.