View Javadoc
1   /*
2    * *************************************************************************************************************************************************************
3    *
4    * TheseFoolishThings: Miscellaneous utilities
5    * http://tidalwave.it/projects/thesefoolishthings
6    *
7    * Copyright (C) 2009 - 2025 by Tidalwave s.a.s. (http://tidalwave.it)
8    *
9    * *************************************************************************************************************************************************************
10   *
11   * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12   * You may obtain a copy of the License at
13   *
14   *     http://www.apache.org/licenses/LICENSE-2.0
15   *
16   * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
17   * CONDITIONS OF ANY KIND, either express or implied.  See the License for the specific language governing permissions and limitations under the License.
18   *
19   * *************************************************************************************************************************************************************
20   *
21   * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
22   * git clone https://github.com/tidalwave-it/thesefoolishthings-src
23   *
24   * *************************************************************************************************************************************************************
25   */
26  package it.tidalwave.actor;
27  
28  import javax.annotation.Nonnegative;
29  import javax.annotation.Nonnull;
30  import java.time.Duration;
31  import java.time.ZoneId;
32  import java.time.ZonedDateTime;
33  import java.time.temporal.ChronoUnit;
34  import java.util.UUID;
35  
36  /***************************************************************************************************************************************************************
37   *
38   * Represents a single task that is possibly decomposed in multiple subtasks and provides support for waiting for its
39   * completion.
40   *
41   * @author  Fabrizio Giudici
42   *
43   **************************************************************************************************************************************************************/
44  public interface Collaboration
45    {
46      /***********************************************************************************************************************************************************
47       *
48       **********************************************************************************************************************************************************/
49      public static final Collaboration NULL_COLLABORATION = new Collaboration()
50        {
51          @Override @Nonnull
52          public Object getOriginatingMessage()
53            {
54              return new Object();
55            }
56  
57          @Override
58          public boolean isCompleted()
59            {
60              return true;
61            }
62  
63          @Override
64          public void waitForCompletion()
65            {
66            }
67  
68          @Override @Nonnull
69          public ZonedDateTime getStartTime()
70            {
71              return ZonedDateTime.of(
72                      0, 0, 0, 0, 0, 0, 0, ZoneId.systemDefault());
73            }
74  
75          @Override @Nonnull
76          public Duration getDuration()
77            {
78              return Duration.of(0, ChronoUnit.SECONDS);
79            }
80  
81          @Override
82          public Object suspend()
83            {
84              return UUID.randomUUID();
85            }
86  
87          @Override
88          public void resume (@Nonnull final Object suspensionToken, @Nonnull final Runnable runnable)
89            {
90            }
91  
92          @Override
93          public void resumeAndDie (@Nonnull final Object suspensionToken)
94            {
95            }
96  
97          @Override
98          public boolean isSuspended()
99            {
100             return false;
101           }
102 
103         @Override
104         public int getDeliveringMessagesCount()
105           {
106             return 0;
107           }
108 
109         @Override
110         public int getPendingMessagesCount()
111           {
112             return 0;
113           }
114 
115         @Override
116         public int getRunningThreadsCount()
117           {
118             return 0;
119           }
120       };
121 
122     /***********************************************************************************************************************************************************
123      * A provider of a {@link Collaboration}.
124      **********************************************************************************************************************************************************/
125     public static interface Provider
126       {
127         /***************************************************************************************************************
128          *
129          * Returns the {@link Collaboration}.
130          *
131          * @return   the {@code Collaboration}
132          *
133          **************************************************************************************************************/
134         @Nonnull
135         public Collaboration getCollaboration();
136       }
137 
138     /***********************************************************************************************************************************************************
139      * Returns the message that originated this {@code Collaboration}.
140      *
141      * @return  the message
142      **********************************************************************************************************************************************************/
143     @Nonnull
144     public Object getOriginatingMessage();
145 
146     /***********************************************************************************************************************************************************
147      * Returns {@code true} if the {@code Collaboration} has been completed.
148      *
149      * @return  {@code true} if the {@code Collaboration} has been completed
150      **********************************************************************************************************************************************************/
151     public boolean isCompleted();
152 
153     /***********************************************************************************************************************************************************
154      * Waits for the completion of this {@code Collaboration}.
155      *
156      * @throws  InterruptedException  if the wait is interrupted
157      **********************************************************************************************************************************************************/
158     public void waitForCompletion()
159             throws InterruptedException;
160 
161     /***********************************************************************************************************************************************************
162      * Return the time when this {@code Collaboration} has been created.
163      *
164      * @return  the creation time
165      **********************************************************************************************************************************************************/
166     @Nonnull
167     public ZonedDateTime getStartTime();
168 
169     /***********************************************************************************************************************************************************
170      * Return the duration of this {@code Collaboration}.
171      *
172      * @return  the duration
173      **********************************************************************************************************************************************************/
174     @Nonnull
175     public Duration getDuration();
176 
177     /***********************************************************************************************************************************************************
178      * Sometimes a {@code Collaboration} must coordinate with the external world, waiting for an external asynchronous
179      * event that cannot be modeled with agents. For instance, a user intervention (e.g. by clicking a button) or an
180      * external piece of software that is not part of the {@code Collaboration} model. In this case, it can be marked
181      * as 'suspended' and in this case it won't be considered completed, even though there are no related pending
182      * messages or working threads. When the external event occurs, call
183      * {@link #resume(java.lang.Object, java.lang.Runnable)}.
184      *
185      * In order to support multiple reasons for suspension, a token is generated and returned. It must be passed to
186      * {@code resume()} for resuming.
187      *
188      * @see #resume(java.lang.Object, java.lang.Runnable)
189      * @see #isSuspended()
190      *
191      * @return   a token representing the reason for the suspension
192      **********************************************************************************************************************************************************/
193     public Object suspend();
194 
195     /***********************************************************************************************************************************************************
196      * Resumes a suspended {@code Collaboration}. It executes the given {@link Runnable} which is expected to send new
197      * messages.
198      *
199      * @see #suspend()
200      * @see #isSuspended()
201      *
202      * @param  suspensionToken  the token representing the reason for the suspension
203      * @param  resumerTask      the code which resumes the {@code Collaboration}
204      **********************************************************************************************************************************************************/
205     public void resume (@Nonnull Object suspensionToken, @Nonnull Runnable resumerTask);
206 
207     /***********************************************************************************************************************************************************
208      * Resumes a suspended {@code Collaboration} and lets it terminate without any further operation.
209      *
210      * @see #suspend()
211      * @see #resume(java.lang.Object, java.lang.Runnable)
212      * @see #isSuspended()
213      *
214      * @param  suspensionToken  the token representing the reason for the suspension
215      **********************************************************************************************************************************************************/
216     public void resumeAndDie (@Nonnull Object suspensionToken);
217 
218     /***********************************************************************************************************************************************************
219      * Returns {@code true} when the current {@code Collaboration} is suspended.
220      *
221      * @see #suspend()
222      * @see #resume(java.lang.Object, java.lang.Runnable)
223      *
224      * @return {@code true} when it's suspended
225      **********************************************************************************************************************************************************/
226     public boolean isSuspended();
227 
228     /***********************************************************************************************************************************************************
229      * Returns the number of messages related to this {@code Collaboration} not yet delivered.
230      *
231      * @return  the number of messages not yet delivered
232      **********************************************************************************************************************************************************/
233     @Nonnegative
234     public int getDeliveringMessagesCount();
235 
236     /***********************************************************************************************************************************************************
237      * Returns the number of messages related to this {@code Collaboration} not yet consumed.
238      *
239      * @return  the number of messages not yet consumed
240      **********************************************************************************************************************************************************/
241     @Nonnegative
242     public int getPendingMessagesCount();
243 
244     /***********************************************************************************************************************************************************
245      * Returns the number of running threads assigned to this {@code Collaboration}.
246      *
247      * @return  the number of threads
248      **********************************************************************************************************************************************************/
249     @Nonnegative
250     public int getRunningThreadsCount();
251   }