/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.trace;

import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.function.Consumer;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public final class ThreadUtils {
	
	private final ThreadInfo info;

	private ThreadUtils(long cid) {
        info = Li.THREAD_INFO.getThreadInfo(new long[]{ cid }, true, true)[0];
	}
    
	public static ThreadUtils get() {
		return get(Thread.currentThread());
	}
	
	public static ThreadUtils get(Thread thread) {
		return new ThreadUtils(thread.getId());
	}
	
	public static void dump(boolean condition, Consumer<String> out) {
		if(condition) {
			ThreadUtils info = ThreadUtils.get();
			if(info.locks() > 0) {
				info.dump(out);
			}
		}
	}
	
	public void dump(Consumer<String> out) {
		out.accept(String.format("THREAD: %s 0x%08X (monitors=%d, locks=%d)", 
            info.getThreadName(), 
            info.getThreadId(),
			info.getLockedMonitors().length,
			info.getLockedSynchronizers().length
        ));
        for(MonitorInfo item : info.getLockedMonitors()) {
            out.accept(String.format(" - MONITOR : %s 0x%08X @ %s",
                item.getClassName(),
                item.getIdentityHashCode(),
                item.getLockedStackFrame()
            ));
        }
        for(LockInfo item : info.getLockedSynchronizers()) {
            out.accept(String.format(" - LOCK : %s 0x%08X", 
                item.getClassName(), 
                item.getIdentityHashCode()
            ));
        }
	}

    public int locks() {
        return info.getLockedMonitors().length + info.getLockedSynchronizers().length;
    }

    private static final class Li { // NOPMD lazy init idiom 
        
        public static final ThreadMXBean THREAD_INFO = ManagementFactory.getThreadMXBean();
		
    }
    
}
