From c3d3d0efc763f463a4f31f6ef20b10142c897a45 Mon Sep 17 00:00:00 2001 From: Kolan Sh Date: Thu, 28 Mar 2013 17:41:39 +0400 Subject: [PATCH] More examples added from https://live.gnome.org/Vala/ThreadingSamples --- .../async-queue-test.vala | 76 ++++++++++++++++ .../live.gnome.org_tutorial/philosophers.vala | 88 +++++++++++++++++++ vala/live.gnome.org_tutorial/run.sh | 10 ++- .../threading-sample.vala | 55 ------------ .../live.gnome.org_tutorial/threads-2.32.vala | 46 ++++++++++ vala/live.gnome.org_tutorial/threads.vala | 46 ++++++++++ 6 files changed, 264 insertions(+), 57 deletions(-) create mode 100644 vala/live.gnome.org_tutorial/async-queue-test.vala create mode 100644 vala/live.gnome.org_tutorial/philosophers.vala delete mode 100644 vala/live.gnome.org_tutorial/threading-sample.vala create mode 100644 vala/live.gnome.org_tutorial/threads-2.32.vala create mode 100644 vala/live.gnome.org_tutorial/threads.vala diff --git a/vala/live.gnome.org_tutorial/async-queue-test.vala b/vala/live.gnome.org_tutorial/async-queue-test.vala new file mode 100644 index 0000000..ce9f4f2 --- /dev/null +++ b/vala/live.gnome.org_tutorial/async-queue-test.vala @@ -0,0 +1,76 @@ +class ThreadCommunication { + + private const int NUMBER_OF_MESSAGES = 200000; + private AsyncQueue async_queue; + + public ThreadCommunication () { + this.async_queue = new AsyncQueue (); + } + + // data object for sending + private class DataBox { + + public int number { get; private set; } + public string name { get; private set; } + + public DataBox (int number, string name) { + this.number = number; + this.name = name; + } + } + + private void* writing_func () { + var timer = new Timer (); + timer.start (); + for (int i = 0; i < NUMBER_OF_MESSAGES; i++) { + // prepare an object to send + var databox = new DataBox (i, @"some text for value $i"); + // send a message to the queue + async_queue.push (databox); + } + // show time result + print ("Pushed %d DataBoxes into AsyncQueue in %f s\n", NUMBER_OF_MESSAGES, timer.elapsed ()); + return null; + } + + private void* reading_func () { + var timer = new Timer (); + timer.start (); + for (int i = 0; i < NUMBER_OF_MESSAGES; i++) { + // receive a message from the queue + var databox = async_queue.pop (); + + // make sure the content is right + assert (i == databox.number); + assert (@"some text for value $i" == databox.name); + + // show one of the strings + if ((NUMBER_OF_MESSAGES / 2) == databox.number) { + print ("\tNO: %d \tTEXT: %s\n", databox.number, databox.name); + } + } + // show time result + print ("Popped %d DataBoxes from AsyncQueue in %f s\n", NUMBER_OF_MESSAGES, timer.elapsed ()); + return null; + } + + public void run () { + try { + unowned Thread thread_a = Thread.create (writing_func, true); + unowned Thread thread_b = Thread.create (reading_func, true); + + // Wait until the threads finish + thread_a.join (); + thread_b.join (); + + } catch (ThreadError e) { + stderr.printf ("%s\n", e.message); + return; + } + } +} + +void main () { + var thread_comm = new ThreadCommunication (); + thread_comm.run (); +} diff --git a/vala/live.gnome.org_tutorial/philosophers.vala b/vala/live.gnome.org_tutorial/philosophers.vala new file mode 100644 index 0000000..5cea545 --- /dev/null +++ b/vala/live.gnome.org_tutorial/philosophers.vala @@ -0,0 +1,88 @@ +/** Fork pool used by the philosophers */ +class Forks { + + private bool[] fork = new bool[5]; // initially false, i.e. not used + + private Cond cond = new Cond (); + private Mutex mutex = new Mutex (); + + // Try to pick up the forks with the designated numbers + public void pick_up (int left, int right) { + mutex.lock (); + while (fork[left] || fork[right]) { + cond.wait (mutex); + } + fork[left] = true; + fork[right] = true; + mutex.unlock (); + } + + // Lay down the forks with the designated numbers + public void lay_down (int left, int right) { + mutex.lock (); + fork[left] = false; + fork[right] = false; + cond.broadcast (); + mutex.unlock (); + } +} + +/** A dining philosopher */ +class Philosopher { + + private int number; // this philosopher's number + private int think_delay; // how long does this philosopher think? + private int eat_delay; // how long does this philosopher eat? + private int left; // left fork number + private int right; // right fork number + private Forks forks; // forks used by all philosophers + + public Philosopher (int number, int think_delay, int eat_delay, Forks forks) { + this.number = number; + this.think_delay = think_delay; + this.eat_delay = eat_delay; + this.forks = forks; + this.left = number == 0 ? 4 : number - 1; + this.right = (number + 1) % 5; + } + + public void* run () { + while (true) { + Thread.usleep (think_delay); + forks.pick_up (left, right); + stdout.printf ("Philosopher %d starts eating...\n", number); + Thread.usleep (eat_delay); + forks.lay_down (left, right); + stdout.printf ("Philosopher %d stops eating...\n", number); + } + } +} + +int main (string[] args) { + + if (!Thread.supported ()) { + error ("Cannot run without thread support."); + } + + var forks = new Forks (); + + Philosopher[] philos = { + new Philosopher (0, 100000, 500000, forks), + new Philosopher (1, 200000, 400000, forks), + new Philosopher (2, 300000, 300000, forks), + new Philosopher (3, 400000, 200000, forks), + new Philosopher (4, 500000, 100000, forks) + }; + + try { + foreach (var philosopher in philos) { + Thread.create (philosopher.run, false); + } + } catch (ThreadError e) { + error ("%s\n", e.message); + } + + new MainLoop ().run (); + + return 0; +} diff --git a/vala/live.gnome.org_tutorial/run.sh b/vala/live.gnome.org_tutorial/run.sh index 29e8704..bc59972 100755 --- a/vala/live.gnome.org_tutorial/run.sh +++ b/vala/live.gnome.org_tutorial/run.sh @@ -1,4 +1,10 @@ #!/bin/sh -valac --thread --pkg glib-2.0 --target-glib=2.32 threading-sample.vala -./threading-sample +# valac --thread --target-glib=2.32 threading-sample.vala \ +valac --thread threads.vala +valac --thread --target-glib=2.32 threads-2.32.vala +valac --thread philosophers.vala +valac --thread async-queue-test.vala + + + diff --git a/vala/live.gnome.org_tutorial/threading-sample.vala b/vala/live.gnome.org_tutorial/threading-sample.vala deleted file mode 100644 index c1fbfb0..0000000 --- a/vala/live.gnome.org_tutorial/threading-sample.vala +++ /dev/null @@ -1,55 +0,0 @@ -public class MyThread : Object { - public ThreadPriority priority { get; private set; } - public int x_times { get; private set; } - - public MyThread (int times, ThreadPriority priority) { - this.priority = priority; - this.x_times = times; - } - - public int run () { - // set the priority: - Thread.self ().set_priority (ThreadPriority.URGENT); - - for (int i = 0; i < this.x_times; i++) { - stdout.printf ("ping! %d/%d\n", i + 1, this.x_times); - Thread.usleep (10000); - } - - // return & exit have the same effect - Thread.exit (42); - return 43; - } -} - -public static int main (string[] args) { - // Check whether threads are supported: - if (Thread.supported () == false) { - stderr.printf ("Threads are not supported!\n"); - return -1; - } - - try { - // Start a thread: - MyThread my_thread = new MyThread (10, ThreadPriority.URGENT); - Thread thread = new Thread.try ("My fst. thread", my_thread.run); - - // Count all running threads: - int threads = 0; - Thread.foreach (() => { - threads++; - }); - - // Output: ``Running threads: 0`` - stdout.printf ("Running threads: %d\n", threads); - - // Wait until thread finishes: - int result = thread.join (); - // Output: `Thread stopped! Return value: 42` - stdout.printf ("Thread stopped! Return value: %d\n", result); - } catch (Error e) { - stdout.printf ("Error: %s\n", e.message); - } - - return 0; -} diff --git a/vala/live.gnome.org_tutorial/threads-2.32.vala b/vala/live.gnome.org_tutorial/threads-2.32.vala new file mode 100644 index 0000000..19411b3 --- /dev/null +++ b/vala/live.gnome.org_tutorial/threads-2.32.vala @@ -0,0 +1,46 @@ +class MyThread { + + private string name; + private int count = 0; + + public MyThread (string name) { + this.name = name; + } + + public void* thread_func () { + while (true) { + stdout.printf ("%s: %i\n", this.name, this.count); + this.count++; + Thread.usleep (Random.int_range (0, 200000)); + } + } +} + +int main () { + if (!Thread.supported ()) { + stderr.printf ("Cannot run without thread support.\n"); + return 1; + } + + var thread_a_data = new MyThread ("A"); + var thread_b_data = new MyThread ("B"); + + try { + // Start two threads + /* With error handling */ + Thread thread_a = new Thread.try ("thread_a", thread_a_data.thread_func); + /* Without error handling (is not using the try/catch) */ + Thread thread_b = new Thread ("thread_b", thread_b_data.thread_func); + + // Wait for threads to finish (this will never happen in our case, but anyway) + thread_a.join (); + thread_b.join (); + + } catch (Error e) { + stderr.printf ("%s\n", e.message); + return 1; + } + + + return 0; +} diff --git a/vala/live.gnome.org_tutorial/threads.vala b/vala/live.gnome.org_tutorial/threads.vala new file mode 100644 index 0000000..c8b95ac --- /dev/null +++ b/vala/live.gnome.org_tutorial/threads.vala @@ -0,0 +1,46 @@ +class MyThread { + + private string name; + private int count = 0; + + public MyThread (string name) { + this.name = name; + } + + public void* thread_func () { + while (true) { + stdout.printf ("%s: %i\n", this.name, this.count); + this.count++; + Thread.usleep (Random.int_range (0, 200000)); + } + } +} + +int main () { + if (!Thread.supported ()) { + stderr.printf ("Cannot run without thread support.\n"); + return 1; + } + + var thread_a_data = new MyThread ("A"); + var thread_b_data = new MyThread ("B"); + + try { + + // Start two threads + unowned Thread thread_a = Thread.create (thread_a_data.thread_func, true); + unowned Thread thread_b = Thread.create (thread_b_data.thread_func, true); + + // Wait for threads to finish (this will never happen in our case, but anyway) + thread_a.join (); + thread_b.join (); + + } catch (ThreadError e) { + stderr.printf ("%s\n", e.message); + return 1; + } + + return 0; +} + +