View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.io;
20  
21  import java.io.IOException;
22  import java.nio.channels.ClosedChannelException;
23  import java.nio.channels.ReadPendingException;
24  import java.util.concurrent.atomic.AtomicBoolean;
25  import java.util.concurrent.atomic.AtomicReference;
26  
27  import org.eclipse.jetty.util.Callback;
28  
29  
30  /* ------------------------------------------------------------ */
31  /** 
32   * A Utility class to help implement {@link EndPoint#fillInterested(Callback)}
33   * by keeping state and calling the context and callback objects.
34   * 
35   */
36  public abstract class FillInterest
37  {
38      private final AtomicReference<Callback> _interested = new AtomicReference<>(null);
39  
40      /* ------------------------------------------------------------ */
41      protected FillInterest()
42      {
43      }
44  
45      /* ------------------------------------------------------------ */
46      /** Call to register interest in a callback when a read is possible.
47       * The callback will be called either immediately if {@link #needsFill()} 
48       * returns true or eventually once {@link #fillable()} is called.
49       * @param context
50       * @param callback
51       * @throws ReadPendingException
52       */
53      public <C> void register(Callback callback) throws ReadPendingException
54      {
55          if (callback==null)
56              throw new IllegalArgumentException();
57          
58          if (!_interested.compareAndSet(null,callback))
59              throw new ReadPendingException();
60          try
61          {
62              if (needsFill())
63                  fillable();
64          }
65          catch(IOException e)
66          {
67              onFail(e);
68          }
69      }
70  
71      /* ------------------------------------------------------------ */
72      /** Call to signal that a read is now possible.
73       */
74      public void fillable()
75      {
76          Callback callback=_interested.get();
77          if (callback!=null && _interested.compareAndSet(callback,null))
78              callback.succeeded();
79      }
80  
81      /* ------------------------------------------------------------ */
82      /**
83       * @return True if a read callback has been registered
84       */
85      public boolean isInterested()
86      {
87          return _interested.get()!=null;
88      }
89      
90      /* ------------------------------------------------------------ */
91      /** Call to signal a failure to a registered interest
92       */
93      public void onFail(Throwable cause)
94      {
95          Callback callback=_interested.get();
96          if (callback!=null && _interested.compareAndSet(callback,null))
97              callback.failed(cause);
98      }
99      
100     /* ------------------------------------------------------------ */
101     public void onClose()
102     {
103         Callback callback=_interested.get();
104         if (callback!=null && _interested.compareAndSet(callback,null))
105             callback.failed(new ClosedChannelException());
106     }
107     
108     /* ------------------------------------------------------------ */
109     @Override
110     public String toString()
111     {
112         return String.format("FillInterest@%x{%b,%s}",hashCode(),_interested.get(),_interested.get());
113     }
114     
115     /* ------------------------------------------------------------ */
116     /** Register the read interest 
117      * Abstract method to be implemented by the Specific ReadInterest to
118      * enquire if a read is immediately possible and if not to schedule a future
119      * call to {@link #fillable()} or {@link #onFail(Throwable)}
120      * @return true if a read is possible
121      * @throws IOException
122      */
123     abstract protected boolean needsFill() throws IOException;
124     
125     
126 }