
org.rapidoid.net.impl.AbstractEventLoop Maven / Gradle / Ivy
package org.rapidoid.net.impl;
import org.rapidoid.annotation.Authors;
import org.rapidoid.annotation.Since;
import org.rapidoid.log.Log;
import java.io.IOException;
import java.nio.channels.ClosedSelectorException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Set;
/*
* #%L
* rapidoid-net
* %%
* Copyright (C) 2014 - 2016 Nikolche Mihajlovski and contributors
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
@Authors("Nikolche Mihajlovski")
@Since("2.0.0")
public abstract class AbstractEventLoop extends AbstractLoop {
protected final Selector selector;
public AbstractEventLoop(String name) {
super(name);
Selector sel;
try {
sel = Selector.open();
} catch (IOException e) {
Log.error("Cannot open selector!", e);
throw new RuntimeException(e);
}
this.selector = sel;
}
private void processKey(SelectionKey key) {
if (key == null || !key.isValid()) {
return;
}
if (key.isAcceptable()) {
Log.trace("accepting", "key", key);
try {
acceptOP(key);
} catch (IOException e) {
failedOP(key, e);
Log.error("accept IO error for key: " + key, e);
} catch (Throwable e) {
failedOP(key, e);
Log.error("accept failed for key: " + key, e);
}
} else if (key.isConnectable()) {
Log.trace("connection event", "key", key);
try {
connectOP(key);
} catch (IOException e) {
failedOP(key, e);
Log.error("connect IO error for key: " + key, e);
} catch (Throwable e) {
failedOP(key, e);
Log.error("connect failed for key: " + key, e);
}
} else if (key.isReadable()) {
Log.trace("reading", "key", key);
try {
readOP(key);
} catch (IOException e) {
failedOP(key, e);
Log.error("read IO error for key: " + key, e);
} catch (Throwable e) {
failedOP(key, e);
Log.error("read failed for key: " + key, e);
}
} else if (key.isWritable()) {
Log.trace("writing", "key", key);
try {
writeOP(key);
} catch (IOException e) {
failedOP(key, e);
Log.error("write IO error for key: " + key, e);
} catch (Throwable e) {
failedOP(key, e);
Log.error("write failed for key: " + key, e);
}
}
}
@Override
protected final void insideLoop() {
try {
doProcessing();
} catch (Throwable e) {
Log.error("Event processing error!", e);
}
try {
selector.select(50);
} catch (IOException e) {
Log.error("Select failed!", e);
}
try {
Set selectedKeys = selector.selectedKeys();
synchronized (selectedKeys) {
Iterator> iter = selectedKeys.iterator();
while (iter.hasNext()) {
SelectionKey key = (SelectionKey) iter.next();
iter.remove();
processKey(key);
}
}
} catch (ClosedSelectorException e) {
// do nothing
}
}
protected abstract void doProcessing();
protected void acceptOP(SelectionKey key) throws IOException {
throw new RuntimeException("Accept operation is not implemented!");
}
protected void connectOP(SelectionKey key) throws IOException {
throw new RuntimeException("Connect operation is not implemented!");
}
protected void readOP(SelectionKey key) throws IOException {
throw new RuntimeException("Accept operation is not implemented!");
}
protected void writeOP(SelectionKey key) throws IOException {
throw new RuntimeException("Accept operation is not implemented!");
}
protected void failedOP(SelectionKey key, Throwable e) {
// ignore the errors by default
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy