/*
* Redberry: symbolic tensor computations.
*
* Copyright (c) 2010-2015:
* Stanislav Poslavsky
* Bolotin Dmitriy
*
* This file is part of Redberry.
*
* Redberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Redberry 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 General Public License
* along with Redberry. If not, see .
*/
package cc.redberry.core.context;
import cc.redberry.core.context.defaults.DefaultContextFactory;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
/**
* This class implements context management logic.
*
* It holds current thread-local context of Redberry session (see description for {@link Context} class).
* It is possible to set context explicitly using {@link #setCurrentContext(Context)} method.
* Each thread is linked to its own context. All child threads created via {@code ExecutorService}
* from {@link #getExecutorService()} have same context.
*
* @author Dmitriy Bolotin
* @author Stanislav Poslavsky
* @since 1.0
*/
public final class ContextManager {
/**
* Thread-local container for the current context
*/
private final static ThreadLocal threadLocalContainer = new ThreadLocal() {
@Override
protected ContextContainer initialValue() {
return new ContextContainer();
}
};
/**
* Thread-local {@code ExecutorService}
*/
private static final ThreadLocal executorService = new ThreadLocal() {
@Override
protected ExecutorService initialValue() {
return Executors.newCachedThreadPool(new CThreadFactory(threadLocalContainer.get()));
}
};
private ContextManager() {
}
/**
* Returns the current context of Redberry session.
*
* @return the current context of Redberry session.
*/
public static Context getCurrentContext() {
return threadLocalContainer.get().context;
}
/**
* This method initializes and sets current session context by the default
* value defined in {@link DefaultContextFactory}. After this step, all
* tensors that exist in the thread will be invalidated.
*
* @return created context
*/
public static Context initializeNew() {
Context context = DefaultContextFactory.INSTANCE.createContext();
threadLocalContainer.get().context = context;
return context;
}
/**
* This method initializes and sets current session context from
* the specified {@code context settings} ({@link ContextSettings}).
* After invocation of this method, all the tensors that exist in
* the current thread will be invalidated.
*
* @return created context
*/
public static Context initializeNew(ContextSettings contextSettings) {
Context context = new Context(contextSettings);
threadLocalContainer.get().context = context;
return context;
}
/**
* Sets current thread-local context to the specified one. After this step, all the
* tensors that exist in the thread will be invalidated.
*
* @param context context
*/
public static void setCurrentContext(Context context) {
threadLocalContainer.get().context = context;
}
/**
* Returns thread-local {@code ExecutorService} with fixed context. All threads linked
* to this {@code ExecutorService} will have same context.
*
* @return thread-local {@code ExecutorService} with fixed context
*/
public static ExecutorService getExecutorService() {
return executorService.get();
}
private static class ContextContainer {
volatile Context context = DefaultContextFactory.INSTANCE.createContext();
}
private static class CThreadFactory implements ThreadFactory {
private final ContextContainer container;
public CThreadFactory(ContextContainer container) {
this.container = container;
}
@Override
public Thread newThread(Runnable r) {
return new Thread(new RunnableWrapper(container, r));
}
}
private static class RunnableWrapper implements Runnable {
private final ContextContainer container;
private final Runnable innerRunnable;
public RunnableWrapper(ContextContainer container, Runnable innerRunnable) {
this.container = container;
this.innerRunnable = innerRunnable;
}
@Override
public void run() {
threadLocalContainer.set(container);
innerRunnable.run();
}
}
}
Ads help maintain this website.