1 /*******************************************************************************
2 
3     Manages ITimeoutClient instances where each one has an individual timeout
4     value. Uses a timer event as timeout notification mechanism.
5 
6     Objects that can time out, the so-called timeout clients, must implement
7     ITimeoutClient. For each client create an ExpiryRegistration instance and
8     pass the object to the ExpiryRegistration constructor.
9     Call ExpiryRegistration.register() to set a timeout for the corresponding
10     client. The timeout() method of each client is then called when it has
11     timed out.
12     To disable the timeout for a client that has not timed out yet, call
13     ExpiryRegistration.unregister() .
14 
15     Initially the object returned by TimerEventTimeoutManager.select_client
16     must be registered to an epoll select dispatcher.
17 
18     Link with:
19         -Llibebtree.a
20 
21     Build flags:
22         -debug=TimeoutManager = verbose output
23 
24     Copyright:
25         Copyright (c) 2009-2016 dunnhumby Germany GmbH.
26         All rights reserved.
27 
28     License:
29         Boost Software License Version 1.0. See LICENSE_BOOST.txt for details.
30         Alternatively, this file may be distributed under the terms of the Tango
31         3-Clause BSD License (see LICENSE_BSD.txt for details).
32 
33 *******************************************************************************/
34 
35 module ocean.io.select.timeout.TimerEventTimeoutManager;
36 
37 
38 import ocean.meta.types.Qualifiers;
39 
40 import ocean.time.timeout.TimeoutManager;
41 
42 import ocean.io.select.client.TimerEvent;
43 
44 import ocean.io.select.client.model.ISelectClient;
45 
46 import core.sys.posix.time: time_t, timespec;
47 
48 debug
49 {
50     import core.stdc.time: ctime;
51     import ocean.io.Stdout;
52 }
53 
54 
55 
56 /******************************************************************************/
57 
58 class TimerEventTimeoutManager : TimeoutManager
59 {
60     import ocean.util.container.map.model.IAllocator;
61 
62     /***************************************************************************
63 
64         TimerEvent for absolute real-time that calls checkTimeouts() when fired.
65 
66     ***************************************************************************/
67 
68     private class TimerEvent : ITimerEvent
69     {
70         /***********************************************************************
71 
72             Constructor
73 
74         ***********************************************************************/
75 
76         this ( )
77         {
78             super(true); // use real-time
79             super.absolute = true; // use absolute time
80         }
81 
82         /***********************************************************************
83 
84             Called when the timer event fires; notifies and unregisters the
85             timed out clients.
86 
87             Params:
88                 n = expiration counter (unused, mandatory)
89 
90             Returns:
91                 true to stay registered in the epoll select dispatcher.
92 
93         ***********************************************************************/
94 
95         protected override bool handle_ ( ulong n )
96         {
97             debug ( TimeoutManager ) Stderr("******** " ~ typeof (this.outer).stringof ~ " expired\n").flush();
98 
99             this.outer.checkTimeouts();
100             return true;
101         }
102     }
103 
104     /***************************************************************************
105 
106         TimerEvent instance
107 
108     ***************************************************************************/
109 
110     private TimerEvent event;
111 
112     /***************************************************************************
113 
114         Constructor
115 
116         Params:
117             allocator = use this bucket element allocator for the expiry
118                 registration to ISelectClient map. If it is null the default map
119                 allocator (BucketElementGCAllocator) is used.
120 
121     ***************************************************************************/
122 
123     public this ( IAllocator allocator = null )
124     {
125         super(allocator);
126         this.event = this.new TimerEvent;
127     }
128 
129     /***************************************************************************
130 
131         Returns:
132             the timer event instance to register in an epoll select dispatcher.
133 
134     ***************************************************************************/
135 
136     public ISelectClient select_client ( )
137     {
138         return this.event;
139     }
140 
141     /***************************************************************************
142 
143         Enables or changes the timer event time.
144 
145         Params:
146             next_expiration_us = wall clock time when the next client will time
147                                  out as UNIX time in microseconds.
148 
149     ***************************************************************************/
150 
151     protected override void setTimeout ( ulong next_expiration_us )
152     {
153         timespec ts = timespec(cast (time_t) (next_expiration_us / 1_000_000),
154                                cast (uint)   (next_expiration_us % 1_000_000) * 1000);
155 
156         this.event.set(ts);
157     }
158 
159     /***************************************************************************
160 
161         Disables the timer event.
162 
163     ***************************************************************************/
164 
165     protected override void stopTimeout ( )
166     {
167         this.event.reset();
168     }
169 }