// Handle TCP traffic, from a client to this server asking for work to be // done. This is called on the TCP reader thread, not a Fork/Join worker // thread. We want to do the bulk TCP read in the TCP reader thread. static void tcp_exec(final AutoBuffer ab) { final int ctrl = ab.getCtrl(); final int task = ab.getTask(); final int flag = ab.getFlag(); assert flag == CLIENT_UDP_SEND; // Client sent a request to be executed? // Act "as if" called from the UDP packet code, by recording the task just // like the packet we will be receiving (eventually). The presence of this // packet is used to stop dup-actions on dup-sends. Racily inserted, keep // only the last one. DTask dt1 = ab._h2o.record_task(task); assert dt1 == null || dt1 instanceof NOPTask : "#" + task + " " + dt1.getClass(); // For TCP, no repeats, so 1st send is only send (except for UDP // timeout retries) // Make a remote instance of this dude from the stream, but only if the // racing UDP packet did not already make one. Start the bulk TCP read. final DTask dt = ab.get(DTask.class); // Here I want to execute on this, but not block for completion in the // TCP reader thread. Jam the task on some F/J thread. UDP.udp .UDPS[ctrl] .pool() .execute( new CountedCompleter() { public void compute() { remexec(dt, ab._h2o, task, ab).close(); tryComplete(); } public boolean onExceptionalCompletion(Throwable ex, CountedCompleter caller) { ex.printStackTrace(); return true; } }); // All done for the TCP thread! Work continues in the FJ thread... }