001/*
002 * Trident - A Multithreaded Server Alternative
003 * Copyright 2014 The TridentSDK Team
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package net.tridentsdk.server.chunk;
018
019import net.tridentsdk.server.world.ChunkSection;
020
021import java.util.concurrent.locks.Lock;
022import java.util.concurrent.locks.ReentrantLock;
023import java.util.function.Consumer;
024import java.util.function.Function;
025
026/**
027 * Allows for higher throughput chunk memory I/O for concurrent access
028 *
029 * @author The TridentSDK Team
030 */
031public class ConcurrentSectionTable {
032    private final ChunkSection[] sections = new ChunkSection[16];
033    private final Lock[] locks = new Lock[16];
034
035    public ConcurrentSectionTable() {
036        for (int i = 0; i < 16; i++) {
037            sections[i] = new ChunkSection((byte) i);
038            locks[i] = new ReentrantLock();
039        }
040    }
041
042    public void lockFully() {
043        for (Lock lock : locks) {
044            lock.lock();
045        }
046    }
047
048    public void release() {
049        for (Lock lock : locks) {
050            lock.unlock();
051        }
052    }
053
054    public ChunkSection get(int i) {
055        return sections[i];
056    }
057
058    public void set(int i, ChunkSection section) {
059        sections[i] = section;
060    }
061
062    public void modify(int i, Consumer<ChunkSection> consumer) {
063        Lock lock = locks[i];
064        lock.lock();
065        try {
066            consumer.accept(sections[i]);
067        } finally {
068            lock.unlock();
069        }
070    }
071
072    public <T> T modifyAndReturn(int i, Function<ChunkSection, T> function) {
073        Lock lock = locks[i];
074        lock.lock();
075        try {
076            return function.apply(sections[i]);
077        } finally {
078            lock.unlock();
079        }
080    }
081}