/* flush current message queue to a registered * console widget, if such a thing exists. * since vmdcon_append() allocates the storage, * for everything, we have to free the msg structs * and the strings. */ int vmdcon_purge(void) { struct vmdcon_msg *msg; const char *res; wkf_mutex_lock(&vmdcon_status_lock); /* purge message queue only if we have a working console window */ if ( ! ((vmdcon_status == VMDCON_UNDEF) || (vmdcon_status == VMDCON_NONE) || ((vmdcon_status == VMDCON_WIDGET) && ((vmdcon_interp == NULL) || (vmdcon_wpath == NULL))) ) ) { wkf_mutex_lock(&vmdcon_output_lock); while (vmdcon_pending != NULL) { msg=vmdcon_pending; switch (vmdcon_status) { case VMDCON_TEXT: fputs(msg->txt,stdout); break; case VMDCON_WIDGET: res = tcl_vmdcon_insert(vmdcon_interp, vmdcon_wpath, vmdcon_mark, msg->txt); /* handle errors writing to a tcl console window. * unregister widget, don't free current message * and append error message into holding buffer. */ if (res) { wkf_mutex_unlock(&vmdcon_status_lock); vmdcon_register(NULL, NULL, vmdcon_interp); wkf_mutex_unlock(&vmdcon_output_lock); vmdcon_printf(VMDCON_ERROR, "Problem writing to text widget: %s\n", res); return 1; } break; default: /* unknown console type */ return 1; } free(msg->txt); vmdcon_pending=msg->next; free(msg); } if (vmdcon_status == VMDCON_TEXT) fflush(stdout); wkf_mutex_unlock(&vmdcon_output_lock); } wkf_mutex_unlock(&vmdcon_status_lock); return 0; }
/* register a tk/tcl widget to be the console window. * we get the widget path directly from tcl, * so we have to create a copy (and free it later). * we also need a pointer to the tcl interpreter. */ int vmdcon_register(const char *w_path, const char *mark, void *interp) { wkf_mutex_lock(&vmdcon_status_lock); vmdcon_interp=interp; /* unregister current console widget */ if(w_path == NULL) { if (vmdcon_wpath != NULL) { free(vmdcon_wpath); free(vmdcon_mark); } vmdcon_wpath=NULL; vmdcon_mark=NULL; /* we have to indicate that no console is available */ if (vmdcon_status == VMDCON_WIDGET) vmdcon_status=VMDCON_NONE; } else { int len; if (vmdcon_wpath != NULL) { free(vmdcon_wpath); free(vmdcon_mark); } len=strlen(w_path); vmdcon_wpath=(char*)malloc(len+1); strcpy(vmdcon_wpath, w_path); len=strlen(mark); vmdcon_mark=(char*)malloc(len+1); strcpy(vmdcon_mark, mark); } wkf_mutex_unlock(&vmdcon_status_lock); /* try to flush pending console log text. */ return vmdcon_purge(); }
/* set current vmdcon status */ void vmdcon_set_status(int status, void *interp) { wkf_mutex_lock(&vmdcon_status_lock); if (interp != NULL) vmdcon_interp=interp; vmdcon_status=status; tcl_vmdcon_set_status_var(vmdcon_interp, status); wkf_mutex_unlock(&vmdcon_status_lock); }
/* append text from to console log buffer to queue. */ int vmdcon_showlog(void) { struct vmdcon_msg *log, *msg; wkf_mutex_lock(&vmdcon_output_lock); log=vmdcon_logmsgs; do { /* append to message queue. */ msg=(struct vmdcon_msg *)malloc(sizeof(struct vmdcon_msg)); msg->txt=(char *) malloc(strlen(log->txt)+1); msg->lvl=VMDCON_ALWAYS; strcpy(msg->txt,log->txt); msg->next=NULL; if (vmdcon_pending == NULL) { vmdcon_pending=msg; vmdcon_lastmsg=msg; } else { vmdcon_lastmsg->next=msg; vmdcon_lastmsg=msg; } log=log->next; } while (log->next != NULL); /* terminate the dmesg output with a newline */ msg=(struct vmdcon_msg *)malloc(sizeof(struct vmdcon_msg)); msg->txt=(char *) malloc(strlen("\n")+1); msg->lvl=VMDCON_ALWAYS; strcpy(msg->txt,"\n"); msg->next=NULL; if (vmdcon_pending == NULL) { vmdcon_pending=msg; vmdcon_lastmsg=msg; } else { vmdcon_lastmsg->next=msg; vmdcon_lastmsg=msg; } log=log->next; wkf_mutex_unlock(&vmdcon_output_lock); return vmdcon_purge(); }
/* append text to console log queue. * we have to make copies as we might get handed * a tcl object or a pointer to some larger buffer. */ int vmdcon_append(int level, const char *txt, int len) { struct vmdcon_msg *msg; char *buf; /* len=0: don't print. len=-1, autodetect. */ if (len == 0 ) return 0; if (len < 0) { len=strlen(txt); } wkf_mutex_lock(&vmdcon_output_lock); /* append to message queue. */ /* but don't print stuff below the current loglevel */ if (level >= vmdcon_loglvl) { /* create copy of text. gets free'd after it has been 'printed'. */ buf=(char *)calloc(len+1,1); strncpy(buf,txt,len); msg=(struct vmdcon_msg *)malloc(sizeof(struct vmdcon_msg)); msg->txt=buf; msg->lvl=level; msg->next=NULL; if (vmdcon_pending == NULL) { vmdcon_pending=msg; vmdcon_lastmsg=msg; } else { vmdcon_lastmsg->next=msg; vmdcon_lastmsg=msg; } } /* messages are added to the log regardless of loglevel. * this way we can silence the log window and still retrieve * useful information with 'vmdcon -dmesg'. */ buf=(char *)calloc(len+1,1); strncpy(buf,txt,len); /* append to log message list. */ msg=(struct vmdcon_msg *)malloc(sizeof(struct vmdcon_msg)); msg->txt=buf; msg->lvl=level; msg->next=NULL; if (vmdcon_logmsgs == NULL) { vmdcon_logmsgs=msg; vmdcon_lastlog=msg; ++vmdcon_loglen; } else { vmdcon_lastlog->next=msg; vmdcon_lastlog=msg; ++vmdcon_loglen; } /* remove message from the front of the queue * in case we have too long a list */ while (vmdcon_loglen > vmdcon_max_loglen) { msg=vmdcon_logmsgs; vmdcon_logmsgs=msg->next; free(msg->txt); free(msg); --vmdcon_loglen; } wkf_mutex_unlock(&vmdcon_output_lock); return 0; }
/* set current vmdcon log level */ void vmdcon_set_loglvl(int lvl) { wkf_mutex_lock(&vmdcon_status_lock); vmdcon_loglvl=lvl; wkf_mutex_unlock(&vmdcon_status_lock); }
extern "C" void * bondsearchthread(void *voidparms) { int i, j, aindex; int paircount = 0; bondsearchthrparms *parms = (bondsearchthrparms *) voidparms; const int threadid = parms->threadid; const int threadcount = parms->threadcount; wkf_mutex_t *pairlistmutex = parms->pairlistmutex; const float *pos = parms->pos; const float *radii = parms->radii; const int totb = parms->totb; const int **boxatom = (const int **) parms->boxatom; const int *numinbox = parms->numinbox; const int **nbrlist = (const int **) parms->nbrlist; const int maxpairs = parms->maxpairs; const float pairdist = parms->pairdist; ResizeArray<int> *pairs = new ResizeArray<int>; float sqdist = pairdist * pairdist; wkfmsgtimer *msgt = wkf_msg_timer_create(5); for (aindex = threadid; (aindex < totb) && (paircount < maxpairs); aindex+=threadcount) { const int *tmpbox, *nbr; tmpbox = boxatom[aindex]; int anbox = numinbox[aindex]; if (((aindex & 255) == 0) && wkf_msg_timer_timeout(msgt)) { char tmpbuf[128]; sprintf(tmpbuf, "%6.2f", (100.0f * aindex) / (float) totb); // XXX: we have to use printf here as msgInfo is not thread-safe. // msgInfo << "vmd_gridsearch_bonds (thread " << threadid << "): " // << tmpbuf << "% complete" << sendmsg; printf("vmd_gridsearch_bonds (thread %d): %s %% complete\n", threadid, tmpbuf); } for (nbr = nbrlist[aindex]; (*nbr != -1) && (paircount < maxpairs); nbr++) { int nnbr=*nbr; const int *nbrbox = boxatom[nnbr]; int nbox=numinbox[nnbr]; int self = (aindex == nnbr) ? 1 : 0; for (i=0; (i<anbox) && (paircount < maxpairs); i++) { int ind1 = tmpbox[i]; const float *p1 = pos + 3L*ind1; // skip over self and already-tested atoms int startj = (self) ? i+1 : 0; for (j=startj; (j<nbox) && (paircount < maxpairs); j++) { int ind2 = nbrbox[j]; const float *p2 = pos + 3L*ind2; float dx = p1[0] - p2[0]; float dy = p1[1] - p2[1]; float dz = p1[2] - p2[2]; float ds2 = dx*dx + dy*dy + dz*dz; // perform distance test, but ignore pairs between atoms // with nearly identical coords if ((ds2 > sqdist) || (ds2 < 0.001)) continue; if (radii) { // Do atom-specific distance check float cut = 0.6f * (radii[ind1] + radii[ind2]); if (ds2 > cut*cut) continue; } pairs->append(ind1); pairs->append(ind2); paircount++; } } } } // setup results pairlist node GridSearchPairlist *head; head = (GridSearchPairlist *) malloc(sizeof(GridSearchPairlist)); head->next = NULL; head->pairlist = pairs; wkf_mutex_lock(pairlistmutex); // lock pairlist before update parms->head = head; wkf_mutex_unlock(pairlistmutex); // unlock pairlist after update wkf_msg_timer_destroy(msgt); return NULL; }