Home | History | Annotate | Download | only in okio
      1 /*
      2  * Copyright (C) 2014 Square, Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package okio;
     17 
     18 /**
     19  * A collection of unused segments, necessary to avoid GC churn and zero-fill.
     20  * This pool is a thread-safe static singleton.
     21  */
     22 final class SegmentPool {
     23   /** The maximum number of bytes to pool. */
     24   // TODO: Is 64 KiB a good maximum size? Do we ever have that many idle segments?
     25   static final long MAX_SIZE = 64 * 1024; // 64 KiB.
     26 
     27   /** Singly-linked list of segments. */
     28   static Segment next;
     29 
     30   /** Total bytes in this pool. */
     31   static long byteCount;
     32 
     33   private SegmentPool() {
     34   }
     35 
     36   static Segment take() {
     37     synchronized (SegmentPool.class) {
     38       if (next != null) {
     39         Segment result = next;
     40         next = result.next;
     41         result.next = null;
     42         byteCount -= Segment.SIZE;
     43         return result;
     44       }
     45     }
     46     return new Segment(); // Pool is empty. Don't zero-fill while holding a lock.
     47   }
     48 
     49   static void recycle(Segment segment) {
     50     if (segment.next != null || segment.prev != null) throw new IllegalArgumentException();
     51     if (segment.shared) return; // This segment cannot be recycled.
     52     synchronized (SegmentPool.class) {
     53       if (byteCount + Segment.SIZE > MAX_SIZE) return; // Pool is full.
     54       byteCount += Segment.SIZE;
     55       segment.next = next;
     56       segment.pos = segment.limit = 0;
     57       next = segment;
     58     }
     59   }
     60 }
     61