1 /*
2  *Copyright (C) 2018 Laurent Tréguier
3  *
4  *This file is part of DLS.
5  *
6  *DLS is free software: you can redistribute it and/or modify
7  *it under the terms of the GNU General Public License as published by
8  *the Free Software Foundation, either version 3 of the License, or
9  *(at your option) any later version.
10  *
11  *DLS is distributed in the hope that it will be useful,
12  *but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *GNU General Public License for more details.
15  *
16  *You should have received a copy of the GNU General Public License
17  *along with DLS.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 module dls.util.disposable_fiber;
22 
23 import core.thread : Fiber;
24 
25 class FiberDisposedException : Exception
26 {
27     this()
28     {
29         super("Fiber disposed");
30     }
31 }
32 
33 class DisposableFiber : Fiber
34 {
35     static bool safeMode;
36     private bool _disposed;
37 
38     static DisposableFiber getThis()
39     {
40         const thisFiber = Fiber.getThis();
41         assert(typeid(thisFiber) == typeid(DisposableFiber));
42         return cast(DisposableFiber) thisFiber;
43     }
44 
45     static void yield()
46     {
47         if (safeMode)
48         {
49             return;
50         }
51 
52         Fiber.yield();
53 
54         if (getThis()._disposed)
55         {
56             throw new FiberDisposedException();
57         }
58     }
59 
60     this(void delegate() dg)
61     {
62         size_t pageSize;
63 
64         version (Windows)
65         {
66             import core.sys.windows.winbase : GetSystemInfo, SYSTEM_INFO;
67 
68             SYSTEM_INFO info;
69             GetSystemInfo(&info);
70             pageSize = cast(size_t) info.dwPageSize;
71         }
72         else version (Posix)
73         {
74             import core.sys.posix.unistd : _SC_PAGESIZE, sysconf;
75 
76             pageSize = cast(size_t) sysconf(_SC_PAGESIZE);
77         }
78         else
79         {
80             pageSize = 4096;
81         }
82 
83         super(dg, pageSize * 32);
84     }
85 
86     void dispose()
87     {
88         _disposed = true;
89     }
90 }