Links

Categories

Tags


« | Main

Simple “multi-threading” class

By Jewe | November 28, 2016

Just an example how you can use co-functions to do “multi-threading” in JewelScript.

I have added a simple “Task Manager” class to one of my script applications. With this script, I can add any custom class implementing the Task interface to the task manager. It will give each task a call subsequently. Co-functions are used to implement the actual thread – hence, the whole thing uses cooperative multi-threading. That means, if a thread does not yield it’s execution time frequently, all other threads are blocked.

Still, the class might come in handy in some script applications. I’m using it to download files in the background in one of my tools, so I can still work with the tool while the downloads are running and I don’t have to wait for them to finish.

//------------------------------------------------------------------------------
// Threading
//------------------------------------------------------------------------------
// Cooperative threads that can run in the background when a Form is idle.
//------------------------------------------------------------------------------

namespace Library::Console::Threading {

using Windows::Console;

//------------------------------------------------------------------------------
// interface Task
//------------------------------------------------------------------------------

interface Task
{
    accessor bool Enabled();
    accessor Enabled(bool);
    accessor string Name();
    method Resume();
    method Dispose();
}

//------------------------------------------------------------------------------
// class DefaultTask
//------------------------------------------------------------------------------

class DefaultTask implements Task
{
    method DefaultTask(const string n)
    {
        name = n;
        enabled = true;
    }
    accessor bool Enabled() { return enabled; }
    accessor Enabled(bool b) { enabled = b; }
    accessor string Name() { return name; }
    method Resume() {}
    method Dispose() {}

    private string name;
    private bool enabled;
}

//------------------------------------------------------------------------------
// class ThreadedTask
//------------------------------------------------------------------------------

class ThreadedTask extends DefaultTask
{
    cofunction Worker(weak ThreadedTask t) {}

    method ThreadedTask(const string name, Worker w)
        extends DefaultTask(name)
    {
        worker = w;
    }
    method Resume()
    {
        worker();
    }
    method Dispose()
    {
        worker = null;
    }

    private Worker worker;
}

//------------------------------------------------------------------------------
// class TaskManager
//------------------------------------------------------------------------------

class TaskManager extends ThreadedTask
{
    method TaskManager()
        extends ThreadedTask("TaskManager", new TaskRunner(this))
    {
        tasks = {};
    }
    method Dispose()
    {
        tasks.enumerate(function(e, a) { e.Task::Dispose(); });
        tasks = null;
        base.Dispose();
    }
    method Add(Task task)
    {
        tasks += task;
    }
    method Remove(const string name)
    {
        for (int index = 0; index < tasks.length; index++)
        {
            if (tasks[index].Name == name)
            {
                tasks = tasks.remove(index, 1);
                break;
            }
        }
    }
    cofunction TaskRunner(weak ThreadedTask tt)
    {
        TaskManager manager = (TaskManager)tt;
        for (;;)
        {
            for (int i = 0; i < manager.tasks.length; i++)
            {
                Task task = manager.tasks[i];
                if (task.Enabled)
                    task.Resume();
                yield;
            }
            yield;
        }
    }

    Task[] tasks;
}

} // end namespace

Topics: code examples, news | Comments Off on Simple “multi-threading” class

Comments are closed.