package php.runtime.ext.core.classes; import php.runtime.Memory; import php.runtime.common.HintType; import php.runtime.env.Environment; import php.runtime.invoke.Invoker; import php.runtime.lang.BaseObject; import php.runtime.memory.ObjectMemory; import php.runtime.reflection.ClassEntity; import java.util.concurrent.*; import static php.runtime.annotation.Reflection.*; @Name("php\\lang\\ThreadPool") public class WrapThreadPool extends BaseObject { protected ExecutorService service; public WrapThreadPool(Environment env, ExecutorService service) { super(env); this.service = service; } public WrapThreadPool(Environment env, ClassEntity clazz) { super(env, clazz); } public ExecutorService getService() { return service; } @Signature private Memory __construct(Environment env, Memory... args){ return Memory.NULL; } @Signature({ @Arg(value = "runnable", type = HintType.CALLABLE), @Arg(value = "env", nativeType = WrapEnvironment.class, optional = @Optional("NULL")) }) public Memory execute(final Environment env, Memory... args){ Environment _env = env; if (!args[1].isNull()) { _env = args[1].toObject(WrapEnvironment.class).getWrapEnvironment(); } final Invoker invoker = Invoker.valueOf(_env, null, args[0]); invoker.setTrace(env.trace()); final Environment final_env = _env; service.execute(new Runnable() { @Override public void run() { Environment.addThreadSupport(final_env); invoker.callNoThrow(); } }); return Memory.NULL; } private ScheduledExecutorService getScheduledExecutorService(Environment env){ if (!(service instanceof ScheduledExecutorService)){ env.exception("Unsupported operation for non-scheduled executor service"); return null; } return (ScheduledExecutorService) service; } @Signature public Memory isScheduled(Environment env, Memory... args){ return service instanceof ScheduledExecutorService ? Memory.TRUE : Memory.FALSE; } @Signature({ @Arg(value = "runnable", type = HintType.CALLABLE), @Arg(value = "env", typeClass = "php\\lang\\Environment", optional = @Optional("NULL")) }) public Memory submit(Environment env, Memory... args){ final Environment _env = args[1].isNull() ? env : args[1].toObject(WrapEnvironment.class).getWrapEnvironment(); final Invoker invoker = Invoker.valueOf(_env, null, args[0]); Future<Memory> future = service.submit(new Callable<Memory>() { @Override public Memory call() throws Exception { return invoker.callNoThrow(); } }); return new ObjectMemory(new WrapFuture(env, future)); } @Signature({ @Arg(value = "runnable", type = HintType.CALLABLE), @Arg("delay"), @Arg(value = "env", typeClass = "php\\lang\\Environment", optional = @Optional("NULL")) }) public Memory schedule(final Environment env, Memory... args){ final Environment _env = args[2].isNull() ? env : args[2].toObject(WrapEnvironment.class).getWrapEnvironment(); final Invoker invoker = Invoker.valueOf(_env, null, args[0]); ScheduledFuture<Memory> future = getScheduledExecutorService(env).schedule(new Callable<Memory>() { @Override public Memory call() throws Exception { Environment.addThreadSupport(_env); return invoker.callNoThrow(); } }, args[1].toLong(), TimeUnit.MILLISECONDS); return new ObjectMemory(new WrapFuture(env, future)); } @Signature public Memory shutdown(Environment env, Memory... args){ service.shutdown(); return Memory.NULL; } @Signature public Memory shutdownNow(Environment env, Memory... args){ service.shutdownNow(); return Memory.NULL; } @Signature public Memory isShutdown(Environment env, Memory... args){ return service.isShutdown() ? Memory.TRUE : Memory.FALSE; } @Signature public Memory isTerminated(Environment env, Memory... args){ return service.isTerminated() ? Memory.TRUE : Memory.FALSE; } @Signature(@Arg("timeout")) public Memory awaitTermination(Environment env, Memory... args) throws InterruptedException { return service.awaitTermination(args[0].toLong(), TimeUnit.MILLISECONDS) ? Memory.TRUE : Memory.FALSE; } @Signature(@Arg("max")) public static Memory createFixed(Environment env, Memory... args){ return new ObjectMemory(new WrapThreadPool(env, Executors.newFixedThreadPool(args[0].toInteger()) )); } @Signature({ @Arg("corePoolSize"), @Arg("maxPoolSize"), @Arg(value = "keepAliveTime", optional = @Optional("0")) }) public static Memory create(Environment env, Memory... args){ int nThreads = args[0].toInteger(); int nMaxThreads = args[1].toInteger(); long keepAliveTime = args[2].toLong(); ThreadPoolExecutor executor = new ThreadPoolExecutor( nThreads, nMaxThreads, keepAliveTime, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>() ); return new ObjectMemory(new WrapThreadPool(env, executor)); } @Signature public static Memory createCached(Environment env, Memory... args){ return new ObjectMemory(new WrapThreadPool(env, Executors.newCachedThreadPool() )); } @Signature public static Memory createSingle(Environment env, Memory... args){ return new ObjectMemory(new WrapThreadPool(env, Executors.newSingleThreadExecutor() )); } @Signature(@Arg("corePoolSize")) public static Memory createScheduled(Environment env, Memory... args){ return new ObjectMemory(new WrapThreadPool(env, Executors.newScheduledThreadPool(args[0].toInteger()) )); } }