java/com/jetbrains/cef/remote/RpcContext.java (69 lines of code) (raw):

package com.jetbrains.cef.remote; import com.jetbrains.cef.remote.thrift.transport.TTransportException; import org.cef.misc.CefLog; import org.cef.misc.Utils; import java.util.concurrent.LinkedBlockingQueue; public class RpcContext { private static final boolean REWIND_QUEUE = Utils.getBoolean("JCEF_REWIND_QUEUE"); // temporary key for advanced teamcity tests private static final RpcExecutor.Rpc NO_RPC = s -> {}; public final CefServer server; private final RpcExecutor myMain; private final RpcExecutor myBackground; private final LinkedBlockingQueue<RpcExecutor.Rpc> myQueue = new LinkedBlockingQueue(); private final Thread myThread; private volatile boolean myClosed = false; public RpcContext(CefServer server) { this.server = server; myMain = new RpcExecutor(server); myBackground = new RpcExecutor(server); myThread = new Thread(() -> { while (true) { try { RpcExecutor.Rpc rpc = myQueue.take(); if (rpc == NO_RPC) return; myBackground.exec(rpc); } catch (InterruptedException e) { CefLog.Warn("RpcContext bg thread interrupted: %s", e.getMessage()); return; } } }); myThread.setName("CefBgThread"); myThread.setDaemon(true); myThread.start(); } public void openTransport(ThriftTransport thriftServer) throws TTransportException { myMain.openTransport(thriftServer); myBackground.openTransport(thriftServer); } public int connect(ThriftTransport thriftBackward, boolean asMaster) { int cid = myMain.connect(thriftBackward, asMaster); myBackground.exec(s -> s.attach(cid)); return cid; } public void invokeLater(RpcExecutor.Rpc rpc) { myQueue.add(rpc); } public void close() { if (myClosed) return; myClosed = true; myQueue.add(NO_RPC); // It will cause bg-thread to stop. if (REWIND_QUEUE) { try { myThread.join(); // wait for all queued rpc } catch (InterruptedException e) { CefLog.Debug("RpcContext join interrupted: %s", e.getMessage()); } } myMain.closeTransport(); myBackground.closeTransport(); } // // Convenience methods // public void exec(RpcExecutor.Rpc r) { myMain.exec(r); } public <T> T execObj(RpcExecutor.RpcObj<T> r) { return myMain.execObj(r); } }