00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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,
00049 this
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;
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;
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) {
00097 delete [] posbuf1;
00098 delete [] posbuf2;
00099 posbuf1 = new float[3L*length];
00100 posbuf2 = new float[3L*length];
00101 curbuf = posbuf1;
00102 curpos = posbuf2;
00103 }
00104 numcoords = length;
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
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 ) {
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
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
00159 if (need2flip) swap4_aligned(pos, 3L*numcoords);
00160 }
00161
00162 void IMDSimThread::send_forces(int num, int *ind, float *forces) {
00163
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