static void DaoMT_RunArrayFunctional( void *p ) { DaoValue **idval; DaoValue *elem, *res = NULL; DaoValue tidint = {DAO_INTEGER}; DaoValue com = {DAO_COMPLEX}; DaoValue *threadid = (DaoValue*)(void*)&tidint; DaoTaskData *self = (DaoTaskData*)p; DaoProcess *clone = self->clone; DaoVmCode *sect = self->sect; DaoArray *param = (DaoArray*) self->param; DaoArray *result = (DaoArray*) self->result; DaoArray *original = param->original; DaoArray *array = original ? original : param; DArray *slices = param->slices; daoint *dims = array->dims; daoint i, id, id2, n = DaoArray_SliceSize( param ); int j, D = array->ndim; int isvec = (D == 2 && (dims[0] ==1 || dims[1] == 1)); int stackBase, vdim = sect->b - 1; DaoMT_InitProcess( self->proto, clone ); tidint.xInteger.value = self->first; stackBase = clone->topFrame->active->stackBase; idval = clone->activeValues + sect->a + 1; for(j=0; j<vdim; j++) idval[j]->xInteger.value = 0; for(i=self->first; i<n; i+=self->step){ idval = clone->stackValues + stackBase + sect->a + 1; id = id2 = (original ? DaoArray_IndexFromSlice( original, slices, i ) : i); if( isvec ){ if( vdim >0 ) idval[0]->xInteger.value = id2; if( vdim >1 ) idval[1]->xInteger.value = id2; }else{ for( j=D-1; j>=0; j--){ int k = id2 % dims[j]; id2 /= dims[j]; if( j < vdim ) idval[j]->xInteger.value = k; } } elem = clone->stackValues[ stackBase + sect->a ]; if( elem == NULL || elem->type != array->etype ){ elem = (DaoValue*)&com; elem->type = array->etype; elem = DaoProcess_SetValue( clone, sect->a, elem ); } DaoArray_GetValue( array, id, elem ); if( sect->b > 6 ) DaoProcess_SetValue( clone, sect->a+6, threadid ); clone->topFrame->entry = self->entry; DaoProcess_Execute( clone ); if( clone->status != DAO_PROCESS_FINISHED ) break; res = clone->stackValues[0]; if( self->funct == DVM_FUNCT_MAP ){ DaoArray_SetValue( result, i, res ); }else if( self->funct == DVM_FUNCT_APPLY ){ DaoArray_SetValue( array, id, res ); } } }
static void DaoMT_Start( DaoProcess *proc, DaoValue *p[], int n ) { DaoProcess *clone; DaoVmCode *vmc, *end; DaoVmCode *sect = DaoGetSectionCode( proc->activeCode ); DaoType *type = DaoProcess_GetReturnType( proc ); DaoFuture *future = DaoFuture_New( type, 0 ); int entry, nop = proc->activeCode[1].code == DVM_NOP; DaoProcess_PutValue( proc, (DaoValue*) future ); if( sect == NULL || DaoMT_PushSectionFrame( proc ) == 0 ) return; entry = proc->topFrame->entry; end = proc->activeRoutine->body->vmCodes->data.codes + proc->activeCode[nop+1].b; clone = DaoVmSpace_AcquireProcess( proc->vmSpace ); DaoProcess_PopFrame( proc ); DaoProcess_SetActiveFrame( proc, proc->topFrame ); DaoMT_InitProcess( proc, clone ); clone->topFrame->entry = entry; /* // Use the cloned process instead of the parent process, in case that // the cloned process will not be joined by the parent process: */ clone->topFrame->outer = clone; future->process = clone; GC_IncRC( clone ); GC_ShiftRC( future, clone->future ); clone->future = future; future->state = DAO_CALL_RUNNING; for(vmc=sect; vmc!=end; vmc++){ int i = -1, code = vmc->code; if( code == DVM_GETVH || (code >= DVM_GETVH_I && code <= DVM_GETVH_C) ){ i = vmc->b; }else if( code == DVM_SETVH || (code >= DVM_SETVH_II && code <= DVM_SETVH_CC) ){ i = vmc->b; } if( i >= 0 ){ /* These values should be shared with the parent thread: */ GC_ShiftRC( proc->activeValues[i], clone->activeValues[i] ); clone->activeValues[i] = proc->activeValues[i]; } } DaoCallServer_AddTask( DaoMT_Start0, clone, p[0]->xEnum.value ); }
static void DaoMT_RunMapFunctional( void *p ) { DaoValue *res; DaoInteger tidint = {DAO_INTEGER,0,0,0,0,0}; DaoValue *threadid = (DaoValue*)(void*)&tidint; DaoTaskData *self = (DaoTaskData*)p; DaoMap *map = (DaoMap*) self->param; DaoList *list2 = (DaoList*) self->result; DaoProcess *clone = self->clone; DaoVmCode *sect = self->sect; DaoType *type = map->ctype; DNode *node = NULL; daoint i = 0; DaoMT_InitProcess( self->proto, clone, 3 ); tidint.value = self->first; type = type && type->nested->size > 1 ? type->nested->items.pType[1] : NULL; for(node=DMap_First( map->value ); node; node=DMap_Next(map->value, node) ){ if( (i++) % self->step != self->first ) continue; if( sect->b >0 ) DaoProcess_SetValue( clone, sect->a, node->key.pValue ); if( sect->b >1 ) DaoProcess_SetValue( clone, sect->a+1, node->value.pValue ); if( sect->b >2 ) DaoProcess_SetValue( clone, sect->a+2, threadid ); clone->topFrame->entry = self->entry; DaoProcess_Execute( clone ); if( clone->status != DAO_PROCESS_FINISHED ) break; res = clone->stackValues[0]; if( self->funct == DVM_FUNCT_MAP ){ self->status |= DaoList_SetItem( list2, res, i-1 ); }else if( self->funct == DVM_FUNCT_APPLY ){ self->status |= DaoValue_Move( res, & node->value.pValue, type ) == 0; }else if( self->funct == DVM_FUNCT_FIND ){ DNode **p = self->node; /* XXX: 2014-11-11 */ if( *p && DaoValue_Compare( (*p)->key.pValue, node->key.pValue ) < 0 ) break; if( res->xInteger.value ){ DMutex_Lock( self->mutex ); if( *p == NULL || DaoValue_Compare( (*p)->key.pValue, node->key.pValue ) >0 ) *p = node; DMutex_Unlock( self->mutex ); break; } } } }
static void DaoMT_RunListFunctional( void *p ) { DaoValue *res; DaoInteger idint = {DAO_INTEGER,0,0,0,0,0}; DaoInteger tidint = {DAO_INTEGER,0,0,0,0,0}; DaoValue *index = (DaoValue*)(void*)&idint; DaoValue *threadid = (DaoValue*)(void*)&tidint; DaoTaskData *self = (DaoTaskData*)p; DaoList *list = (DaoList*) self->param; DaoList *list2 = (DaoList*) self->result; DaoProcess *clone = self->clone; DaoVmCode *sect = self->sect; DaoValue **items = list->items.items.pValue; daoint i, n = list->items.size; DaoMT_InitProcess( self->proto, clone ); tidint.value = self->first; for(i=self->first; i<n; i+=self->step){ idint.value = i; if( sect->b >0 ) DaoProcess_SetValue( clone, sect->a, items[i] ); if( sect->b >1 ) DaoProcess_SetValue( clone, sect->a+1, index ); if( sect->b >2 ) DaoProcess_SetValue( clone, sect->a+2, threadid ); clone->topFrame->entry = self->entry; DaoProcess_Execute( clone ); if( clone->status != DAO_PROCESS_FINISHED ) break; res = clone->stackValues[0]; if( self->funct == DVM_FUNCT_MAP ){ self->status |= DaoList_SetItem( list2, res, i ); }else if( self->funct == DVM_FUNCT_APPLY ){ self->status |= DaoList_SetItem( list, res, i ); }else if( self->funct == DVM_FUNCT_FIND ){ if( *self->index >= 0 && *self->index < i ) break; if( res->xInteger.value ){ DMutex_Lock( self->mutex ); if( *self->index < 0 || i < *self->index ) *self->index = i; DMutex_Unlock( self->mutex ); break; } } } }
static void DaoMT_RunIterateFunctional( void *p ) { DaoInteger idint = {DAO_INTEGER,0,0,0,0,0}; DaoInteger tidint = {DAO_INTEGER,0,0,0,0,0}; DaoValue *index = (DaoValue*)(void*)&idint; DaoValue *threadid = (DaoValue*)(void*)&tidint; DaoTaskData *self = (DaoTaskData*)p; DaoProcess *clone = self->clone; DaoVmCode *sect = self->sect; daoint i, n = self->param->xInteger.value; DaoMT_InitProcess( self->proto, clone ); tidint.value = self->first; for(i=self->first; i<n; i+=self->step){ idint.value = i; if( sect->b >0 ) DaoProcess_SetValue( clone, sect->a, index ); if( sect->b >1 ) DaoProcess_SetValue( clone, sect->a+1, threadid ); clone->topFrame->entry = self->entry; DaoProcess_Execute( clone ); if( clone->status != DAO_PROCESS_FINISHED ) break; } }
static void DaoMT_Start( DaoProcess *proc, DaoValue *p[], int n ) { DaoProcess *clone; DaoVmCode *vmc, *end, *sect; DaoType *type = DaoProcess_GetReturnType( proc ); DaoFuture *future = DaoFuture_New( type, 0 ); int entry, nop = proc->activeCode[1].code == DVM_NOP; DaoProcess_PutValue( proc, (DaoValue*) future ); sect = DaoProcess_InitCodeSection( proc, 0 ); if( sect == NULL ) return; entry = proc->topFrame->entry; end = proc->activeRoutine->body->vmCodes->data.codes + proc->activeCode[nop+1].b; clone = DaoVmSpace_AcquireProcess( proc->vmSpace ); DaoProcess_PopFrame( proc ); DaoMT_InitProcess( proc, clone, 0 ); clone->topFrame->entry = entry; /* // Use the cloned process instead of the parent process, in case that // the cloned process will not be joined by the parent process: */ clone->topFrame->outer = clone; future->process = clone; GC_IncRC( clone ); GC_Assign( & clone->future, future ); future->state = DAO_CALL_RUNNING; for(vmc=sect; vmc!=end; vmc++){ int i = -1, code = vmc->code; if( code == DVM_GETVH || (code >= DVM_GETVH_I && code <= DVM_GETVH_C) ){ i = vmc->b; }else if( code == DVM_SETVH || (code >= DVM_SETVH_II && code <= DVM_SETVH_CC) ){ i = vmc->b; } if( i >= 0 ) DaoValue_Move( proc->activeValues[i], & clone->activeValues[i], NULL ); } DaoCallServer_AddTask( DaoMT_Start0, clone, p[0]->xEnum.value ? clone : NULL ); }