summaryrefslogtreecommitdiff
path: root/gee/task.vala
blob: 00cf74f76c81de8cc6baa34b85ec1a9bcbdf06c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/* task.vala
 *
 * Copyright (C) 2013  Maciej Piechotka
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
 *
 * Author:
 * 	Maciej Piechotka <uzytkownik2@gmail.com>
 */
namespace Gee {
	[CCode (scope = "async")]
	public delegate G Task<G>();

	/**
	 * Schedules a task to execute asynchroniously. Internally one
	 * of threads from pool will execute the task.
	 *
	 * Note: There is limited number of threads unless environment variable
	 *   ``GEE_NUM_THREADS`` is set to -1. It is not advised to call I/O or
	 *   block inside the taks. If necessary it is possible to create a new one
	 *   by anyther call.
	 *
	 * @param task Task to be executed
	 * @return Future value returned by task
	 * @see async_task
	 * @since 0.11.0
	 */
	public Future<G> task<G>(owned Task<G> task) throws GLib.ThreadError {
		TaskData<G> tdata = new TaskData<G>();
		tdata.function = (owned)task;
		tdata.promise = new Promise<G>();
		Future<G> result = tdata.promise.future;
		TaskData.get_async_pool ().add ((owned)tdata);
		return result;
	}

	/**
	 * Continues the execution asynchroniously in helper thread. Internally
	 * one of threads from pool will execute the task.
	 *
	 * Note: There is limited number of threads unless environment variable
	 *   ``GEE_NUM_THREADS`` is set to -1. It is not advised to call I/O or
	 *   block inside the taks. If necessary it is possible to create a new one
	 *   by anyther call.
	 *
	 * @see task
	 * @since 0.11.0
	 */
	public async void async_task() throws GLib.ThreadError {
		task<bool>(async_task.callback);
	}

	[Compact]
	internal class TaskData<G> {
		public Task<G> function;
		public Promise<G> promise;
		public void run() {
			promise.set_value(function());
		}
		private static GLib.Once<ThreadPool<TaskData>> async_pool;
		internal static unowned ThreadPool<TaskData> get_async_pool () {
			return async_pool.once(() => {
				int num_threads = (int)GLib.get_num_processors ();
				string? gee_num_threads_str = Environment.get_variable("GEE_NUM_THREADS");
				if (gee_num_threads_str != null) {
					int64 result;
					if (int64.try_parse (gee_num_threads_str, out result)) {
						num_threads = (int)result;
					}
				}
				try {
					return new ThreadPool<TaskData>.with_owned_data((tdata) => {
						tdata.run();
					}, num_threads, false);
				} catch (ThreadError err) {
					Process.abort ();
				}
			});
		}
	}
}