changeset 878:5125f75dd6f2

impl MCTask
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Sun, 24 Jan 2021 15:52:40 +0900
parents e2a0e5a65a3d
children 88cdab47903f
files src/parallel_execution/CMakeLists.txt src/parallel_execution/MCTaskManagerImpl.cbc src/parallel_execution/MCTaskManagerImpl.h src/parallel_execution/MCWorker.h src/parallel_execution/ModelChecking/MCWorker.cbc src/parallel_execution/SingleLinkedQueue.cbc src/parallel_execution/examples/DPP/PhilsImpl.cbc src/parallel_execution/examples/DPP2/PhilsImpl.cbc src/parallel_execution/generate_context.pl src/parallel_execution/generate_stub.pl src/parallel_execution/lib/Gears/Stub.pm
diffstat 11 files changed, 448 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/src/parallel_execution/CMakeLists.txt	Sat Jan 23 21:02:49 2021 +0900
+++ b/src/parallel_execution/CMakeLists.txt	Sun Jan 24 15:52:40 2021 +0900
@@ -153,7 +153,7 @@
   TARGET
   DPP2
   SOURCES
-  TaskManagerImpl.cbc CPUWorker.cbc SynchronizedQueue.cbc examples/DPP2/AtomicTImpl.cbc SingleLinkedStack.cbc examples/DPP2/PhilsImpl.cbc examples/DPP2/main.cbc examples/DPP2/ForkImpl.cbc ModelChecking/crc32.c ModelChecking/memory.c ModelChecking/state_db.c AtomicReference.cbc
+  TaskManagerImpl.cbc CPUWorker.cbc SynchronizedQueue.cbc examples/DPP2/AtomicTImpl.cbc SingleLinkedStack.cbc examples/DPP2/PhilsImpl.cbc examples/DPP2/main.cbc examples/DPP2/ForkImpl.cbc ModelChecking/crc32.c ModelChecking/memory.c ModelChecking/state_db.c AtomicReference.cbc ModelChecking/MCWorker.cbc
 )
 
 GearsCommand(
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/MCTaskManagerImpl.cbc	Sun Jan 24 15:52:40 2021 +0900
@@ -0,0 +1,206 @@
+#include "../context.h"
+#interface "TaskManager.h"
+#interface "Iterator.h"
+#interface "Queue.h"
+#interface "Worker.h"
+
+#include <stdio.h>
+#include <unistd.h>
+
+void createWorkers(struct Context* context, TaskManagerImpl* taskManager);
+
+TaskManager* createMCTaskManagerImpl(struct Context* context, int numCPU, int numGPU, int numIO) {
+    struct TaskManager* taskManager = new TaskManager();
+    taskManager->spawnTasks = C_spawnTasksTaskManagerImpl;
+    taskManager->spawn = C_spawnTaskManagerImpl;
+    taskManager->shutdown  = C_shutdownTaskManagerImpl;
+    taskManager->incrementTaskCount = C_incrementTaskCountTaskManagerImpl;
+    taskManager->decrementTaskCount = C_decrementTaskCountTaskManagerImpl;
+    taskManager->setWaitTask = C_setWaitTaskTaskManagerImpl;
+    struct MCTaskManagerImpl* taskManagerImpl = new TaskManagerImpl();
+    // 0...numIO-1 IOProcessor
+    // numIO...numIO+numGPU-1 GPUProcessor
+    // numIO+numGPU...numIO+numGPU+numCPU-1 CPUProcessor
+    taskManagerImpl->io = 0;
+    taskManagerImpl->gpu = numIO;
+    taskManagerImpl->cpu = numIO+numGPU;
+    taskManagerImpl->maxCPU = numIO+numGPU+numCPU;
+    taskManagerImpl->numWorker = taskManagerImpl->maxCPU;
+    taskManagerImpl->sendGPUWorkerIndex = taskManagerImpl->gpu;
+    taskManagerImpl->sendCPUWorkerIndex = taskManagerImpl->cpu;
+    taskManagerImpl->taskCount = 0;
+    taskManagerImpl->loopCounter = 0;
+    createWorkers(context, taskManagerImpl);
+    taskManager->taskManager = (union Data*)taskManagerImpl;
+    return taskManager;
+}
+
+void createWorkers(struct Context* context, MCMCTaskManagerImpl* taskManager) {
+    int i = 0;
+    taskManager->workers = (Worker**)ALLOCATE_PTR_ARRAY(context, Worker, taskManager->maxCPU);
+    for (;i<taskManager->gpu;i++) {
+        Queue* queue = createSynchronizedQueue(context);
+        taskManager->workers[i] = (Worker*)createCPUWorker(context, i, queue);
+    }
+    for (;i<taskManager->cpu;i++) {
+        Queue* queue = createSynchronizedQueue(context);
+#ifdef USE_CUDAWorker
+        taskManager->workers[i] = (Worker*)createCUDAWorker(context, i, queue,0);
+#else
+        taskManager->workers[i] = (Worker*)createCPUWorker(context, i, queue);
+#endif
+    }
+    for (;i<taskManager->maxCPU;i++) {
+        Queue* queue = createSynchronizedQueue(context);
+        taskManager->workers[i] = (Worker*)createCPUWorker(context, i, queue);
+    }
+}
+
+__code spawnTasksMCTaskManagerImpl(struct TaskManagerImpl* taskManager, struct Element* taskList, __code next1(...)) {
+    taskManager->taskList = taskList;
+    goto spawnTasksMCTaskManagerImpl1();
+}
+
+__code spawnTasksMCTaskManagerImpl1(struct TaskManagerImpl* taskManagerImpl, struct TaskManager* taskManager) {
+    if (taskManagerImpl->taskList == NULL) {
+        goto spawnTasksMCTaskManagerImpl2();
+    }
+    struct Context* task = (struct Context*)taskManagerImpl->taskList->data;
+    taskManagerImpl->taskList = taskManagerImpl->taskList->next;
+    goto taskManager->setWaitTask(task, spawnTasksMCTaskManagerImpl1);
+}
+
+__code spawnTasksMCTaskManagerImpl1_stub(struct Context* context) {
+    MCTaskManagerImpl* taskManagerImpl = (TaskManagerImpl*)GearImpl(context, TaskManager, taskManager);
+    MCTaskManager* taskManager = &Gearef(context, TaskManager)->taskManager->TaskManager;
+    goto spawnTasksMCTaskManagerImpl1(context, taskManagerImpl, taskManager);
+}
+
+__code spawnTasksMCTaskManagerImpl2(struct TaskManagerImpl* taskManager, struct Element* taskList, __code next1(...)) {
+    taskManager->taskList = taskList;
+    goto spawnTasksMCTaskManagerImpl3();
+}
+
+__code spawnTasksMCTaskManagerImpl3(struct TaskManagerImpl* taskManagerImpl, __code next1(...), struct TaskManager* taskManager) {
+    if (taskManagerImpl->taskList == NULL) {
+        goto next1(...);
+    }
+    struct Context* task = (struct Context*)taskManagerImpl->taskList->data;
+    taskManagerImpl->taskList = taskManagerImpl->taskList->next;
+    goto taskManager->spawn(task, spawnTasksMCTaskManagerImpl3);
+}
+
+__code spawnTasksMCTaskManagerImpl3_stub(struct Context* context) {
+    MCTaskManagerImpl* taskManagerImpl = (TaskManagerImpl*)GearImpl(context, TaskManager, taskManager);
+    enum Code next1 = Gearef(context, MCTaskManager)->next1;
+    MCTaskManager* taskManager = &Gearef(context, TaskManager)->taskManager->TaskManager;
+    goto spawnTasksMCTaskManagerImpl3(context, taskManagerImpl, next1, taskManager);
+}
+
+__code setWaitTaskMCTaskManagerImpl(struct TaskManagerImpl* taskManager, struct Context* task, __code next(...)) {
+    int i = taskManager->loopCounter;
+    if (task->idg+i < task->maxIdg) {
+        struct Queue* queue = GET_WAIT_LIST(task->data[task->idg + i]);
+        taskManager->loopCounter++;
+        goto queue->put(task, setWaitTaskMCTaskManagerImpl);
+    }
+    taskManager->loopCounter = 0;
+    goto incrementTaskCountMCTaskManagerImpl();
+}
+
+__code incrementTaskCountMCTaskManagerImpl(struct TaskManagerImpl* taskManager, __code next(...)) {
+    __sync_fetch_and_add(&taskManager->taskCount, 1);
+    goto next(...);
+}
+
+__code decrementTaskCountMCTaskManagerImpl(struct TaskManagerImpl* taskManager, __code next(...)) {
+    __sync_fetch_and_sub(&taskManager->taskCount, 1);
+    goto next(...);
+}
+
+__code spawnMCTaskManagerImpl(struct TaskManagerImpl* taskManagerImpl, struct Context* task, __code next(...), struct TaskManager* taskManager) {
+    task->taskManager = taskManager;
+    if (task->idgCount == 0) {
+        // iterator task is normal task until spawned
+        if (task->iterator != NULL && task->iterate == 0) {
+            pthread_mutex_unlock(&taskManagerImpl->mutex);
+            struct Iterator* iterator = task->iterator;
+            goto iterator->exec(task, taskManagerImpl->cpu - taskManagerImpl->gpu, next(...));
+        }
+        goto taskSend();
+    }
+    pthread_mutex_unlock(&taskManagerImpl->mutex);
+    goto next(...);
+}
+
+__code spawnMCTaskManagerImpl_stub(struct Context* context) {
+    MCTaskManagerImpl* taskManagerImpl = (TaskManagerImpl*)GearImpl(context, TaskManager, taskManager);
+    struct Context* task = Gearef(context, MCTaskManager)->task;
+    MCTaskManager* taskManager = &Gearef(context, TaskManager)->taskManager->TaskManager;
+    goto spawnMCTaskManagerImpl(context,
+                              taskManagerImpl,
+                              task,
+                              Gearef(context, MCTaskManager)->next,
+                              taskManager);
+}
+
+
+__code taskSend(struct MCTaskManagerImpl* taskManager, struct Context* task, __code next(...)) {
+    // set workerId
+    if (task->gpu) {
+        goto taskSend1();
+    } else {
+        goto taskSend2();
+    }
+}
+
+__code taskSend1(struct MCTaskManagerImpl* taskManager, struct Context* task, __code next(...)) {
+    int workerId = taskManager->sendGPUWorkerIndex;
+    if (++taskManager->sendGPUWorkerIndex >= taskManager->cpu) {
+        taskManager->sendGPUWorkerIndex = taskManager->gpu;
+    }
+    pthread_mutex_unlock(&taskManager->mutex);
+    struct Queue* queue = taskManager->workers[workerId]->tasks;
+    goto queue->put(task, next(...));
+}
+
+__code taskSend2(struct MCTaskManagerImpl* taskManager, struct Context* task, __code next(...)) {
+    int workerId = taskManager->sendCPUWorkerIndex;
+    if (++taskManager->sendCPUWorkerIndex >= taskManager->maxCPU) {
+        taskManager->sendCPUWorkerIndex = taskManager->cpu;
+    }
+    pthread_mutex_unlock(&taskManager->mutex);
+    struct Queue* queue = taskManager->workers[workerId]->tasks;
+    goto queue->put(task, next(...));
+}
+
+__code shutdownMCTaskManagerImpl(struct TaskManagerImpl* taskManager, __code next(...)) {
+    if (taskManager->taskCount != 0) {
+        usleep(1000);
+        goto shutdownMCTaskManagerImpl();
+    }
+    int i = taskManager->loopCounter;
+    if (i < taskManager->numWorker) {
+        struct Queue* tasks = taskManager->workers[i]->tasks;
+        goto tasks->put(NULL, shutdownMCTaskManagerImpl1);
+    }
+
+    taskManager->loopCounter = 0;
+    goto shutdownMCTaskManagerImpl2();
+}
+
+__code shutdownMCTaskManagerImpl1(struct TaskManagerImpl* taskManager, __code next(...)) {
+    taskManager->loopCounter++;
+    goto shutdownMCTaskManagerImpl();
+}
+
+__code shutdownMCTaskManagerImpl2(struct TaskManagerImpl* taskManager, __code next(...)) {
+    int i = taskManager->loopCounter;
+    if (i < taskManager->numWorker) {
+        pthread_join(taskManager->workers[i]->thread, NULL);
+        taskManager->loopCounter++;
+        goto shutdownMCTaskManagerImpl2();
+    }
+    taskManager->loopCounter = 0;
+    goto next(...);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/MCTaskManagerImpl.h	Sun Jan 24 15:52:40 2021 +0900
@@ -0,0 +1,16 @@
+typedef struct MCTaskManagerImpl <> impl MCTaskManager {
+  int numWorker;
+  int sendCPUWorkerIndex;
+  int sendGPUWorkerIndex;
+  int taskCount;
+  pthread_mutex_t mutex;
+  struct Queue* activeQueue;
+  struct Worker** workers;
+  struct Element* taskList;
+  int loopCounter;
+  int cpu;
+  int gpu;
+  int io;
+  int maxCPU;
+  __code next(...);
+} MCTaskManagerImpl;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/MCWorker.h	Sun Jan 24 15:52:40 2021 +0900
@@ -0,0 +1,7 @@
+typedef struct MCWorker <> {
+  pthread_mutex_t mutex;
+  pthread_cond_t cond;
+  struct Context* context;
+  int id;
+  int loopCounter;
+} MCWorker;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parallel_execution/ModelChecking/MCWorker.cbc	Sun Jan 24 15:52:40 2021 +0900
@@ -0,0 +1,124 @@
+#include "../../context.h"
+#interface "TaskManager.h"
+#interface "Worker.h"
+#interface "Iterator.h"
+#interface "Queue.h"
+
+static void startWorker(Worker* worker);
+
+Worker* createMCWorker(struct Context* context, int id, Queue* queue) {
+    struct Worker* worker = new Worker();
+    struct MCWorker* mcWorker = new MCWorker();
+    worker->worker = (union Data*)mcWorker;
+    worker->tasks = queue;
+    mcWorker->id = id;
+    mcWorker->loopCounter = 0;
+    worker->taskReceive = C_taskReceiveMCWorker;
+    worker->shutdown = C_shutdownMCWorker;
+    pthread_create(&worker->thread, NULL, (void*)&startWorker, worker);
+    return worker;
+}
+
+static void startWorker(struct Worker* worker) {
+    struct MCWorker* mcWorker = &worker->worker->MCWorker;
+    mcWorker->context = NEW(struct Context);
+    initContext(mcWorker->context);
+    Gearef(mcWorker->context, Worker)->worker = (union Data*)worker;
+    Gearef(mcWorker->context, Worker)->tasks = worker->tasks;
+    goto meta(mcWorker->context, worker->taskReceive);
+}
+
+__code taskReceiveMCWorker(struct MCWorker* worker, struct Queue* tasks) {
+    goto tasks->take(getTaskMCWorker);
+}
+
+__code getTaskMCWorker(struct MCWorker* mcWorker, struct Context* task, struct Worker* worker) {
+    if (!task) {
+        goto worker->shutdown(); // end thread
+    }
+    task->worker = worker;
+    enum Code taskCg = task->next;
+    task->next = C_odgCommitMCWorker; // commit outputDG after task exec
+    goto meta(task, taskCg); // switch task context
+}
+
+__code getTaskMCWorker_stub(struct Context* context) {
+    MCWorker* mcWorker = (MCWorker*)GearImpl(context, Worker, worker);
+    Worker* worker = &Gearef(context,Worker)->worker->Worker;
+    struct Context* task = &Gearef(context, Queue)->data->Context;
+    goto getTaskMCWorker(context, mcWorker, task, worker);
+}
+
+__code odgCommitMCWorker(struct MCWorker* worker, struct Context* task) {
+    if (task->iterate) {
+        struct Iterator* iterator = task->iterator;
+        goto iterator->barrier(task, odgCommitMCWorker1, odgCommitMCWorker6);
+    } else {
+        goto odgCommitMCWorker1();
+    }
+}
+
+__code odgCommitMCWorker_stub(struct Context* context) {
+    // switch worker context
+    struct Context* workerContext = context->worker->worker->MCWorker.context;
+    Gearef(workerContext, Worker)->worker = (union Data*)context->worker;
+    Gearef(workerContext, Worker)->task = context;
+    MCWorker* mcWorker = (MCWorker*)GearImpl(workerContext, Worker, worker);
+    goto odgCommitMCWorker(workerContext,
+                            mcWorker,
+                            context);
+}
+
+__code odgCommitMCWorker1(struct MCWorker* worker, struct Context* task) {
+    int i = worker->loopCounter;
+    if (task->odg+i < task->maxOdg) {
+        goto odgCommitMCWorker2();
+    }
+    worker->loopCounter = 0;
+    struct TaskManager* taskManager = task->taskManager;
+    goto taskManager->decrementTaskCount(odgCommitMCWorker6);
+}
+
+__code odgCommitMCWorker2(struct MCWorker* worker, struct Context* task) {
+    int i = worker->loopCounter;
+    struct Queue* queue = GET_WAIT_LIST(task->data[task->odg+i]);
+    goto queue->isEmpty(odgCommitMCWorker3, odgCommitMCWorker5);
+}
+
+__code odgCommitMCWorker3(struct MCWorker* worker, struct Context* task) {
+    int i = worker->loopCounter;
+    struct Queue* queue = GET_WAIT_LIST(task->data[task->odg+i]);
+    goto queue->take(odgCommitMCWorker4);
+}
+
+__code odgCommitMCWorker4(struct MCWorker* worker, struct Context* task, struct Context* waitTask) {
+    if (__sync_fetch_and_sub(&waitTask->idgCount, 1) == 1) { // atomic decrement idg counter(__sync_fetch_and_sub function return initial value of waitTask->idgCount point)
+        struct TaskManager* taskManager = waitTask->taskManager;
+        goto taskManager->spawn(waitTask, odgCommitMCWorker2);
+    }
+    goto odgCommitMCWorker2();
+}
+
+__code odgCommitMCWorker4_stub(struct Context* context) {
+    MCWorker* mcWorker     = (MCWorker*)GearImpl(context, Worker, worker);
+    struct Context* task     = Gearef(context, Worker)->task;
+    struct Context* waitTask = &Gearef(context, Queue)->data->Context;
+    goto odgCommitMCWorker4(context,
+                             mcWorker,
+                             task,
+                             waitTask);
+}
+
+__code odgCommitMCWorker5(struct MCWorker* worker, struct Context* task) {
+    worker->loopCounter++;
+    goto odgCommitMCWorker1();
+}
+
+__code odgCommitMCWorker6(struct MCWorker* worker, struct Context* task) {
+    struct Worker* taskWorker = task->worker;
+    goto taskWorker->taskReceive(taskWorker->tasks);
+}
+
+__code shutdownMCWorker(struct MCWorker* worker) {
+    goto exit_code();
+}
--- a/src/parallel_execution/SingleLinkedQueue.cbc	Sat Jan 23 21:02:49 2021 +0900
+++ b/src/parallel_execution/SingleLinkedQueue.cbc	Sun Jan 24 15:52:40 2021 +0900
@@ -10,10 +10,6 @@
     queue->queue = (union Data*)singleLinkedQueue;
     singleLinkedQueue->top  = new Element();
     singleLinkedQueue->last = singleLinkedQueue->top;
-    queue->take  = C_takeSingleLinkedQueue;
-    queue->put  = C_putSingleLinkedQueue;
-    queue->isEmpty = C_isEmptySingleLinkedQueue;
-    queue->clear = C_clearSingleLinkedQueue;
     return queue;
 }
 
--- a/src/parallel_execution/examples/DPP/PhilsImpl.cbc	Sat Jan 23 21:02:49 2021 +0900
+++ b/src/parallel_execution/examples/DPP/PhilsImpl.cbc	Sun Jan 24 15:52:40 2021 +0900
@@ -15,7 +15,7 @@
 // } PhilsImpl;
 // ----
 
-Phils *createPhilsImpl(struct Context *context, int id, AtomicT<int> right, AtomicT<int> left){
+Phils* createPhilsImpl(struct Context *context, int id, AtomicT<int> right, AtomicT<int> left){
     struct Phils* phils = new Phils();
     struct PhilsImpl* phils_impl = new PhilsImpl();
     phils->phils = (union Data *)phils_impl;
--- a/src/parallel_execution/examples/DPP2/PhilsImpl.cbc	Sat Jan 23 21:02:49 2021 +0900
+++ b/src/parallel_execution/examples/DPP2/PhilsImpl.cbc	Sun Jan 24 15:52:40 2021 +0900
@@ -35,12 +35,12 @@
 
 __code putdown_rfork(struct PhilsImpl* phils, __code next(...)) {
     struct AtomicT_int* right_fork = phils->Rightfork;
-    goto right_fork->set(0, putdown_lfork);
+    goto right_fork->set(-1, putdown_lfork);
 }
 
 __code putdown_lfork(struct PhilsImpl* phils, __code next(...)) {
     struct AtomicT_int* left_fork = phils->Leftfork;
-    goto left_fork->set(0, thinking);
+    goto left_fork->set(-1, thinking);
 
 }
 
@@ -51,12 +51,12 @@
 
 __code pickup_rfork(struct PhilsImpl* phils, __code next(...)) {
     struct AtomicT_int* right_fork = phils->Rightfork;
-    goto right_fork->checkAndSet(-1, 0, pickup_lfork, pickup_rfork);
+    goto right_fork->checkAndSet(-1, phils->self, pickup_lfork, pickup_rfork);
 }
 
 __code pickup_lfork(struct PhilsImpl* phils, __code next(...)) {
     struct AtomicT_int* left_fork = phils->Leftfork;
-    goto left_fork->checkAndSet(-1, 0, pickup_rfork, eating);
+    goto left_fork->checkAndSet(-1, phils->self, pickup_rfork, eating);
 
 }
 
--- a/src/parallel_execution/generate_context.pl	Sat Jan 23 21:02:49 2021 +0900
+++ b/src/parallel_execution/generate_context.pl	Sun Jan 24 15:52:40 2021 +0900
@@ -121,8 +121,21 @@
   my ($typed_variable, $generics) = parsed_generics_from_tree($tree);
   my ($type_var, $type_ins) = check_use_generics($typed_variable, $generics, $gears->{generics_list});
 
-  convertGenerics($type_var, $type_ins);
+  my $modify_list = convertGenerics($type_var, $type_ins);
+  my @mod;
 
+  if (%$modify_list) {
+    for my $ftype (qw/cbc header/) {
+      for my $fname (keys %{$modify_list->{$ftype}}) {
+        my $fileInfo = $modify_list->{$ftype}->{$fname};
+        for my $item (grep { $_->{before_impl} } @{$fileInfo}) {
+          print STDERR "@{$item->{before_impl}}\n";
+        }
+      }
+    }
+  }
+
+  #p @mod;
   $gears->tree2create_context_h($tree);
 }
 
@@ -535,11 +548,13 @@
 
         my $replaceType  = $type;
         my $replaceImpls = $impl;
+        my $targetImpl   = $impl;
 
         $replaceType =~ s/$type/${type}_$defType/;
         my $repimpl = 0;
         if (defined $typed_variables->{$impl}) {
           $replaceImpls =~ s/$type/${type}_$defType/;
+          $targetImpl   =~ s/$type/${type}_$defType/;
           $replaceImpls =~ s/$/_$defType/;
           $repimpl = 1;
         }
@@ -555,7 +570,13 @@
         if ($impl eq $replaceImpls) { #not impl
           push(@{$modifyList->{cbc}->{$file}},{before => [$type], after => [$replaceType]});
         } else { #impl
-          push(@{$modifyList->{cbc}->{$file}},{before => [$type, $impl], after => [$replaceType, $replaceImpls]});
+          #push(@{$modifyList->{cbc}->{$file}},{before => [$type, $impl], after => [$replaceType, $replaceImpls]});
+          push(@{$modifyList->{cbc}->{$file}},
+                {
+                  before      => [$type], after      => [$replaceType],
+                  before_impl => [$impl], after_impl => [$replaceImpls]
+                }
+              );
         }
 
         my @cbc_cont;
@@ -564,7 +585,7 @@
         while (my $line = <$fh> ){
           $line =~ s/$type(<.*>)?/$replaceType/g;
           if ($repimpl) {
-            $line =~ s/$impl(<.*>)?/$replaceImpls/g;
+            $line =~ s/${targetImpl}(<.*>)?/$replaceImpls/g;
           }
           $line =~ s/${type_v}([\s\*])/$defType$1/;
           push(@cbc_cont, $line);
@@ -576,9 +597,6 @@
     }
   }
 
-  #p $modifyList;
-
-  #p $typed_variables;
 
   # for my $type (keys %$typed_variables) {
   #   #my @cfiles = grep { /\.c$/ } keys  %{$typed_variables->{$type}->{_caller}};
@@ -594,6 +612,7 @@
   #  }
   #  close $fh;
   #}
+  return $modifyList;
 }
 
 
--- a/src/parallel_execution/generate_stub.pl	Sat Jan 23 21:02:49 2021 +0900
+++ b/src/parallel_execution/generate_stub.pl	Sun Jan 24 15:52:40 2021 +0900
@@ -78,6 +78,7 @@
 my $generateHaveOutputStub = { counter => undef, list           => undef };
 my $replaceCodeGearNames = {};
 my $isGmain;
+my $constructorInfo = {};
 
 
 # this for statement is main routine
@@ -89,6 +90,9 @@
       $cbc_content = Gears::Stub->generate_new_main(cbc_path => $fn,  cbc_content => $cbc_content);
       getDataGear($fn, $cbc_content);
     }
+    if (%$constructorInfo) { #replace constructor
+        $cbc_content = Gears::Stub->replaceConstructor($constructorInfo, $implInterfaceInfo, $cbc_content);
+    }
     generateDataGear($fn, $cbc_content);
 }
 
@@ -164,6 +168,7 @@
                     &getDataGear($cbc_source_path,slurpCbCFiles($cbc_source_path));
                 }
                 $implInterfaceInfo->{genConstructor} = 0;
+                $constructorInfo = Gears::Stub->parsedConstructor(\@content);
             } elsif(/^(.*)par goto (\w+)\((.*)\)/) {
                 debug_print("getDataGear",__LINE__, $_) if $opt_debug;
                 my $codeGearName = $2;
--- a/src/parallel_execution/lib/Gears/Stub.pm	Sat Jan 23 21:02:49 2021 +0900
+++ b/src/parallel_execution/lib/Gears/Stub.pm	Sun Jan 24 15:52:40 2021 +0900
@@ -162,5 +162,64 @@
   $s;
 }
 
+sub parsedConstructor {
+  my ($class, $lines) = @_;
+  my $inConst = undef;
+  my $info    = {};
+
+  for my $line (@$lines) {
+    next unless $line;
+    #Queue* createSingleLinkedQueue(struct Context* context) {
+    if ($line =~ /(\w+)\*?\s+create(\w+)\(/) {
+      $inConst = 1;
+    }
+
+    next unless ($inConst);
+
+    if ($line =~ /(\w+)\-\>(\w+)\s*=\s*(\w+)/) {
+      $info->{$1}->{$2} =  $3;
+    }
+
+    if ($line =~ /^}/) {
+      $inConst = 0;
+    }
+  }
+
+  return $info;
+}
+
+sub replaceConstructor {
+  my ($class, $constructorInfo, $implInterfaceInfo, $cbc_content) = @_;
+  my $interfaceName = lcfirst($implInterfaceInfo->{interface});
+  my @constructorCodeGears = keys %{$constructorInfo->{$interfaceName}};
+  my @interfaceCodeGears   = keys %{$implInterfaceInfo->{parsedInterfaceInfo}->{codeName}};
+
+  #generate  interface->method = C_method
+  if ($implInterfaceInfo->{genConstructor}) {
+    #constructor declaration is perfect
+    return $cbc_content;
+  }
+  return $cbc_content;
+
+  #for my $codeGear (keys $constructorInfo->{$interfaceName}) {
+  #}
+
+  #p $constructorInfo;
+  #p $implInterfaceInfo;
+  ## replace interface->method = method --> interface->method = C_methodImpl
+  #my @aaa = grep { exists $implInterfaceInfo->{parsedInterfaceInfo}->{$_} } @constructorCodeGears;
+  ##if ((scalar(@constructorCodeGears) == scalar(@interfaceCodeGears)) || $implInterfaceInfo->{genConstructor}) {
+
+
+  ## generate interface->method = C_methodImpl
+  #my %wantMethods = map { $_ => 0 }  @interfaceCodeGears;
+  #for (@constructorCodeGears) {
+  #  $wantMethods{$_} = 1; #find
+  #}
+  #my @generateMethods = grep { $wantMethods{$_} == 0  } @interfaceCodeGears;
+  ##p @generateMethods;
+  return $cbc_content;
+}
+
 
 1;