13c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller/*
23c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Copyright (C) 2014 Square, Inc.
33c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
43c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License");
53c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * you may not use this file except in compliance with the License.
63c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * You may obtain a copy of the License at
73c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
83c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *      http://www.apache.org/licenses/LICENSE-2.0
93c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller *
103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Unless required by applicable law or agreed to in writing, software
113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS,
123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * See the License for the specific language governing permissions and
143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * limitations under the License.
153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */
163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpackage okio;
173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller/**
193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * A collection of unused segments, necessary to avoid GC churn and zero-fill.
203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * This pool is a thread-safe static singleton.
213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */
223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerfinal class SegmentPool {
233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  static final SegmentPool INSTANCE = new SegmentPool();
243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /** The maximum number of bytes to pool. */
263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  // TODO: Is 64 KiB a good maximum size? Do we ever have that many idle segments?
273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  static final long MAX_SIZE = 64 * 1024; // 64 KiB.
283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /** Singly-linked list of segments. */
303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private Segment next;
313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  /** Total bytes in this pool. */
333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  long byteCount;
343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  private SegmentPool() {
363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  Segment take() {
393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    synchronized (this) {
403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      if (next != null) {
413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        Segment result = next;
423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        next = result.next;
433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        result.next = null;
443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        byteCount -= Segment.SIZE;
453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller        return result;
463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      }
473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    return new Segment(); // Pool is empty. Don't zero-fill while holding a lock.
493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller
513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  void recycle(Segment segment) {
523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    if (segment.next != null || segment.prev != null) throw new IllegalArgumentException();
533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    synchronized (this) {
543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      if (byteCount + Segment.SIZE > MAX_SIZE) return; // Pool is full.
553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      byteCount += Segment.SIZE;
563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      segment.next = next;
573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      segment.pos = segment.limit = 0;
583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller      next = segment;
593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller    }
603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller  }
613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller}
62