1 /******************************************************************************
2 3 Task extension which makes it possible to store exceptions from a callback
4 so that is gets thrown after the task is resumed. This is useful for
5 providing meaningful stacktraces which point to the origin of the faulty
6 operation rather than to the event loop context.
7 8 Usage example:
9 See the documented unittest of the ExceptionForwarding struct
10 11 Copyright:
12 Copyright (c) 2009-2016 dunnhumby Germany GmbH.
13 All rights reserved.
14 15 License:
16 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
17 Alternatively, this file may be distributed under the terms of the Tango
18 3-Clause BSD License (see LICENSE_BSD.txt for details).
19 20 ******************************************************************************/21 22 moduleocean.task.extensions.ExceptionForwarding;
23 24 version (unittest)
25 {
26 importocean.core.Test;
27 importocean.task.Task;
28 importcore.thread;
29 }
30 31 /******************************************************************************
32 33 Task extension to be used with the `TaskWith` class.
34 35 ******************************************************************************/36 37 structExceptionForwarding38 {
39 publicExceptionto_throw;
40 41 voidonResumed ( )
42 {
43 if (this.to_throw !isnull)
44 {
45 // reset the reference so it won't throw again46 // if the same fiber handles an exception and suspends again47 autoto_throw = this.to_throw;
48 this.to_throw = null;
49 throwto_throw;
50 }
51 }
52 }
53 54 ///55 unittest56 {
57 classExceptionExternal : Exception58 {
59 this ( )
60 {
61 super("external");
62 }
63 }
64 65 classMyTask : TaskWith!(ExceptionForwarding)
66 {
67 boolcaught = false;
68 69 overrideprotectedvoidrun ( )
70 {
71 try72 {
73 // when the following call to `this.suspend()` exit (== after74 // resuming by a callback or the scheduler), the stored75 // exception (if any) will be thrown76 this.suspend();
77 }
78 catch (ExceptionExternale)
79 {
80 caught = true;
81 }
82 }
83 }
84 85 // create a task and assign it to a worker fiber86 autotask = newMyTask;
87 task.assignTo(newWorkerFiber(10240));
88 89 // will start the task (which then yields immediately)90 task.resume();
91 92 // makes stored exception instance thrown from within the task when93 // resumed94 task.extensions.exception_forwarding.to_throw = newExceptionExternal;
95 task.resume();
96 test(task.caught);
97 }