package org.processwarp.android;

import android.os.Handler;

public class Worker implements Runnable {
    /**
     * Delegate for implement by service.
     */
    public interface Delegate {
        void workerRelayCommand(Worker caller, CommandPacket packet);
    }

    /** Delegate instance for pass packet. */
    private Delegate delegate;
    /** Handler for run loop. */
    private Handler handler;
    /** Process-id bundled for process. */
    private String myPid;
    /** Node-id of this node. */
    private String myNid;

    /**
     * Initialize worker and create VM by native method.
     * @param delegate Delegate for implement by service.
     * @param myNid Node-id of this node.
     * @param myPid Process-id for new vm.
     * @param rootTid Root thread-id for new vm.
     * @param procAddr Address of process information for new vm.
     * @param masterNid Node-id of master node for new vm.
     */
    public void initialize(Delegate delegate, String myNid, String myPid,
                           long rootTid, long procAddr, String masterNid) {
        this.delegate = delegate;
        this.myNid = myNid;
        this.myPid = myPid;

        workerInitialize(this, myNid, myPid, rootTid, procAddr, masterNid);

        this.handler = new Handler();
    }

    /**
     * Get Process-id bundled for process.
     * @return Process-id bundled for process.
     */
    public String getPid() {
        return myPid;
    }

    @Override
    public  void run() {
        workerExecute(myPid);
        handler.postDelayed(this, 1);
    }

    /**
     * When receive packet from another node or another module to worker, relay it by NDK.
     * @param pid Process-id bundled to packet.
     * @param dstNid Destination node-id.
     * @param srcNid Source node-id, should be my node-id, THIS, or NONE.
     * @param module Target module.
     * @param content Packet content string of JSON.
     */
    public void relayWorkerCommand(String pid, String dstNid, String srcNid,
                                   int module, String content) {
        workerRelayCommand(pid, dstNid, srcNid, module, content);
    }

    /**
     * When worker require send a packet, relay command by command type.
     * @param pid Process-id bundled to packet.
     * @param dstNid Destination node-id.
     * @param srcNid Source node-id, should be my node-id, THIS, or NONE.
     * @param module Target module.
     * @param content Packet content string of JSON.
     */
    private void workerSendCommand(String pid, String dstNid, String srcNid,
                                   int module, String content) {
        CommandPacket packet = new CommandPacket();
        packet.pid = pid;
        packet.dstNid = dstNid;
        packet.srcNid = srcNid;
        packet.module = module;
        packet.content = content;
        delegate.workerRelayCommand(this, packet);
    }

    private native void workerInitialize(Worker worker, String myNid, String myPid, long rootTid,
                                         long procAddr, String masterNid);
    private native void workerRelayCommand(String pid, String dstNid, String srcNid,
                                           int module, String content);
    private native void workerExecute(String pid);
    private native void workerQuit(String pid);
}

@@ -55,16 +55,66 @@
 ndler;%0A%0A
+import java.util.concurrent.locks.ReentrantLock;%0A%0A
 public c
@@ -580,16 +580,122 @@
 g myNid;
+%0A    /** Mutex for execute native methods serial. */%0A    private ReentrantLock lock = new ReentrantLock();
 %0A%0A    /*
@@ -1319,16 +1319,55 @@
 myPid;%0A%0A
+        lock.lock();%0A        try %7B%0A    
         
@@ -1434,16 +1434,72 @@
 erNid);%0A
+        %7D finally %7B%0A            lock.unlock();%0A        %7D
 %0A       
@@ -1751,29 +1751,125 @@
     
-workerExecute(myPid);
+lock.lock();%0A        try %7B%0A            workerExecute(myPid);%0A        %7D finally %7B%0A            lock.unlock();%0A        %7D
 %0A   
@@ -2404,32 +2404,71 @@
 ring content) %7B%0A
+        lock.lock();%0A        try %7B%0A    
         workerRe
@@ -2513,24 +2513,81 @@
 , content);%0A
+        %7D finally %7B%0A            lock.unlock();%0A        %7D%0A
     %7D%0A%0A    /

add mutex for execute native methods serial