All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.rapidoidx.net.impl.AbstractEventLoop Maven / Gradle / Ivy

The newest version!
package org.rapidoidx.net.impl;

/*
 * #%L
 * rapidoid-x-net
 * %%
 * Copyright (C) 2014 - 2015 Nikolche Mihajlovski and contributors
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see .
 * #L%
 */

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;

import org.rapidoid.annotation.Authors;
import org.rapidoid.annotation.Since;
import org.rapidoid.log.Log;

@Authors("Nikolche Mihajlovski")
@Since("3.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.debug("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.debug("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.debug("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.debug("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(getSelectorTimeout());
		} catch (IOException e) {
			Log.error("Select failed!", e);
		}

		try {
			Set selectedKeys = selector.selectedKeys();
			synchronized (selectedKeys) {
				if (!selectedKeys.isEmpty()) {
					Iterator iter = selectedKeys.iterator();

					while (iter.hasNext()) {
						SelectionKey key = (SelectionKey) iter.next();
						iter.remove();

						processKey(key);
					}
				}
			}
		} catch (ClosedSelectorException e) {
			// do nothing
		}
	}

	protected long getSelectorTimeout() {
		return 10;
	}

	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