00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * RCS INFORMATION: 00011 * 00012 * $RCSfile: IMDSimThread.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.18 $ $Date: 2019年01月17日 21:20:59 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * A multithreaded implementation of the interactive MD 00019 * coordinate/force communication update loop. 00020 ***************************************************************************/ 00021 00022 #include <string.h> 00023 #include <stdio.h> 00024 #include "vmdsock.h" 00025 #include "IMDMgr.h" 00026 #include "IMDSimThread.h" 00027 #include "Inform.h" 00028 #include "utilities.h" 00029 00030 extern "C" void * imdreaderthread(void *v) { 00031 IMDSimThread *st = (IMDSimThread *)v; 00032 return st->reader(v); 00033 } 00034 00035 IMDSimThread::IMDSimThread(const char *host, int port) : IMDSim(host, port) { 00036 curpos = curbuf = posbuf1 = posbuf2 = NULL; 00037 time2die = 0; 00038 00039 if (!isConnected()) 00040 return; 00041 00042 deadsocket = 0; 00043 00044 wkf_mutex_init(&sockmutex); 00045 wkf_mutex_init(&coordmutex); 00046 00047 if (wkf_thread_create(&readerthread, 00048 imdreaderthread, // my thread routine 00049 this // context for thread 00050 )) { 00051 msgErr << "IMDSimThread: unable to create thread" << sendmsg; 00052 } else { 00053 msgInfo << "Using multithreaded IMD implementation." << sendmsg; 00054 } 00055 } 00056 00057 IMDSimThread::~IMDSimThread() { 00058 time2die = 1; // time2die is modified here only!!! 00059 void *status; 00060 00061 if (isConnected()) { 00062 if (wkf_thread_join(readerthread, &status)) { 00063 msgErr << "IMDSimThread: unable to join thread" << sendmsg; 00064 } 00065 } 00066 delete [] posbuf1; 00067 delete [] posbuf2; 00068 disconnect(); 00069 } 00070 00071 void *IMDSimThread::reader(void *) { 00072 IMDType type; 00073 int32 length; 00074 while (!deadsocket && !time2die) { 00075 if (!vmdsock_selread(sock, 0)) { 00076 vmd_msleep(1); 00077 continue; 00078 } 00079 type = imd_recv_header(sock, &length); 00080 00081 switch (type) { 00082 case IMD_FCOORDS: process_coordinates(length); break; 00083 case IMD_ENERGIES: process_energies(length); break; 00084 case IMD_MDCOMM: process_mdcomm(length); break; 00085 case IMD_IOERROR: deadsocket = 1; break; 00086 default: break; // Don't need to read data 00087 } 00088 } 00089 wkf_mutex_lock(&sockmutex); 00090 disconnect(); 00091 wkf_mutex_unlock(&sockmutex); 00092 return NULL; 00093 } 00094 00095 void IMDSimThread::process_coordinates(int32 length) { 00096 if (numcoords < length) { // Need to resize 00097 delete [] posbuf1; 00098 delete [] posbuf2; 00099 posbuf1 = new float[3L*length]; 00100 posbuf2 = new float[3L*length]; 00101 curbuf = posbuf1; 00102 curpos = posbuf2; // should I lock? 00103 } 00104 numcoords = length; // should I lock? 00105 00106 int errcode = imd_recv_fcoords(sock, numcoords, curbuf); 00107 00108 if (errcode) { 00109 msgErr << "Error reading remote coordinates!" << sendmsg; 00110 deadsocket = 1; 00111 } else { 00112 // swap the buffers and announce that new coordinates are ready 00113 wkf_mutex_lock(&coordmutex); 00114 float *tmp = curpos; 00115 curpos = curbuf; 00116 curbuf = tmp; 00117 new_coords_ready = 1; 00118 wkf_mutex_unlock(&coordmutex); 00119 } 00120 } 00121 00122 void IMDSimThread::process_energies(int32 /* length */) { 00123 wkf_mutex_lock(&coordmutex); 00124 00125 int errcode = imd_recv_energies(sock, &imdEnergies); 00126 00127 if (errcode) { 00128 msgErr << "Error reading energies!" << sendmsg; 00129 deadsocket = 1; 00130 } else { 00131 if (need2flip) swap4_aligned(&imdEnergies, sizeof(imdEnergies) / 4); 00132 } 00133 00134 wkf_mutex_unlock(&coordmutex); 00135 } 00136 00137 // This should never happen, but I'll handle it in case it does 00138 void IMDSimThread::process_mdcomm(int32 length) { 00139 int32 *ind = new int32[length]; 00140 float *f = new float[3L*length]; 00141 00142 int errcode = imd_recv_mdcomm(sock, length, ind, f); 00143 00144 if (errcode) { 00145 msgErr << "Error reading MDComm-style forces!" << sendmsg; 00146 deadsocket = 1; 00147 } 00148 delete [] ind; 00149 delete [] f; 00150 } 00151 00152 void IMDSimThread::get_next_ts(float *pos, IMDEnergies *buf) { 00153 wkf_mutex_lock(&coordmutex); 00154 memcpy(pos, curpos, 3L*numcoords*sizeof(float)); 00155 memcpy(buf, &imdEnergies, sizeof(IMDEnergies)); 00156 new_coords_ready = 0; 00157 wkf_mutex_unlock(&coordmutex); 00158 // swap outside of the mutex - yeah baby! 00159 if (need2flip) swap4_aligned(pos, 3L*numcoords); 00160 } 00161 00162 void IMDSimThread::send_forces(int num, int *ind, float *forces) { 00163 // Total data sent will be one int and three floats for each atom 00164 if (need2flip) { 00165 swap4_aligned(ind, num); 00166 swap4_aligned(forces, 3L*num); 00167 } 00168 00169 wkf_mutex_lock(&sockmutex); 00170 if (isConnected()) { 00171 if (imd_send_mdcomm(sock, num, ind, forces)) { 00172 msgErr << "Error sending MDComm indices+forces" << sendmsg; 00173 deadsocket = 1; 00174 } 00175 } 00176 wkf_mutex_unlock(&sockmutex); 00177 } 00178 00179 void IMDSimThread::pause() { 00180 wkf_mutex_lock(&sockmutex); 00181 if (isConnected() && (getSimState() == IMDRUNNING)) { 00182 simstate = IMDPAUSED; 00183 imd_pause(sock); 00184 } 00185 wkf_mutex_unlock(&sockmutex); 00186 } 00187 00188 void IMDSimThread::unpause() { 00189 wkf_mutex_lock(&sockmutex); 00190 if (isConnected() && (getSimState() == IMDPAUSED)) { 00191 simstate = IMDRUNNING; 00192 imd_pause(sock); 00193 } 00194 wkf_mutex_unlock(&sockmutex); 00195 } 00196 00197 void IMDSimThread::detach() { 00198 wkf_mutex_lock(&sockmutex); 00199 if (isConnected()) { 00200 simstate = IMDOFFLINE; 00201 imd_disconnect(sock); 00202 deadsocket = 1; 00203 } 00204 wkf_mutex_unlock(&sockmutex); 00205 } 00206 00207 void IMDSimThread::kill() { 00208 wkf_mutex_lock(&sockmutex); 00209 if (isConnected()) { 00210 simstate = IMDOFFLINE; 00211 imd_kill(sock); 00212 deadsocket = 1; 00213 } 00214 wkf_mutex_unlock(&sockmutex); 00215 } 00216 00217 void IMDSimThread::set_transrate(int rate) { 00218 wkf_mutex_lock(&sockmutex); 00219 if (isConnected()) { 00220 imd_trate(sock, rate); 00221 } 00222 wkf_mutex_unlock(&sockmutex); 00223 } 00224