package org.zstack.core.defer; import org.zstack.utils.Utils; import org.zstack.utils.logging.CLogger; import java.util.HashMap; import java.util.Map; public class Defer { private static ThreadLocal<Map<String, DeferStack<Runnable>>> stack = new ThreadLocal<Map<String, DeferStack<Runnable>>>(); private static final CLogger logger = Utils.getLogger(Defer.class); private static final String EXCEPTION_STACK = "exception"; private static final String NON_EXCEPTION_STACK = "nonException"; private static DeferStack<Runnable> getExceptionStack() { Map<String, DeferStack<Runnable>> s = stack.get(); if (s == null) { s = new HashMap<String, DeferStack<Runnable>>(); stack.set(s); } DeferStack<Runnable> sg = s.get(EXCEPTION_STACK); if (sg == null) { sg = new DeferStack<Runnable>(); s.put(EXCEPTION_STACK, sg); } return sg; } private static DeferStack<Runnable> getNonExceptionStack() { Map<String, DeferStack<Runnable>> s = stack.get(); if (s == null) { s = new HashMap<String, DeferStack<Runnable>>(); stack.set(s); } DeferStack<Runnable> sg = s.get(NON_EXCEPTION_STACK); if (sg == null) { sg = new DeferStack<Runnable>(); s.put(NON_EXCEPTION_STACK, sg); } return sg; } public static void guard(Runnable r) { DeferStack<Runnable> sg = getExceptionStack(); sg.push(r); } public static void defer(Runnable r) { DeferStack<Runnable> sg = getNonExceptionStack(); sg.push(r); } static void runDefer(int top) { DeferStack<Runnable> sg = getNonExceptionStack(); int count = sg.size() - top; for (int i=0; i<count; i++) { try { Runnable r = sg.pop(); r.run(); } catch (Throwable e) { logger.warn("a unhandled exception happened", e); } } } static void pushNonExceptionTop() { DeferStack<Runnable> sg = getNonExceptionStack(); sg.pushTop(); } static int popNonExceptionTop() { DeferStack<Runnable> sg = getNonExceptionStack(); return sg.popTop(); } static int getNonExceptionStackTop() { DeferStack<Runnable> sg = getNonExceptionStack(); return sg.getTop(); } static int getNonExceptionStackSize() { DeferStack<Runnable> sg = getNonExceptionStack(); return sg.size(); } static void pushExceptionTop() { DeferStack<Runnable> sg = getExceptionStack(); sg.pushTop(); } static int popExceptionTop() { DeferStack<Runnable> sg = getExceptionStack(); return sg.popTop(); } static void rollbackExceptionStack(String sourceLocation, int top) { DeferStack<Runnable> sg = getExceptionStack(); int count = sg.size() - top; for (int i=0; i<count; i++) { try { Runnable r = sg.pop(); r.run(); } catch (Throwable e) { logger.warn("A unhandled exception happened during calling defer in " + sourceLocation, e); } } } static void revertExceptionStack(int top) { DeferStack<Runnable> sg = getExceptionStack(); sg.revert(top); } static int getExceptionStackTop() { DeferStack<Runnable> sg = getExceptionStack(); return sg.getTop(); } static int getExceptionStackSize() { DeferStack<Runnable> sg = getExceptionStack(); return sg.size(); } }