///////////////////////////////////////////////////////////////////////// // MMFmgr.cpp - Provides management of shared memory for IPC // // ver 1.1 // // Language: Visual C++ 2008 // // Platform: Dell Precision T7400, Vista Ultimate, SP1 // // Application: Help for CSE687 - Object Oriented Design, Project #2 // // Author: Jim Fawcett, CST 4-187, Syracuse University // // (315) 443-3948, jfawcett@twcny.rr.com // ///////////////////////////////////////////////////////////////////////// #include "MMFmgr.h" #include "..\Threads\locks.h" #include //----< construct RWToggle synchronizer >-------------------------------- // // RWToggle instances have read and write events. One is always signaled // and the other is always unsignaled. It is used to cause the MMF // reader to block while writing and the writer to block while reading RWToggle::RWToggle(std::string name, int role) : name_(name), role_(role) { std::string temp = name + "ReaderEvent"; hRead_ = CreateEventA(0,TRUE,TRUE,temp.c_str()); if(hRead_ == NULL) throw std::exception("\n\ncan't create read event\n\n"); temp = name + "WriterEvent"; hWrite_ = CreateEventA(0,TRUE,FALSE,temp.c_str()); if(hWrite_ == NULL) throw std::exception("\n\ncan't create write event\n\n"); readReady = false; setWrite(); } //----< close the read and write toggle events >------------------------- RWToggle::~RWToggle() { CloseHandle(hRead_); CloseHandle(hWrite_); } //----< put toggle in read mode >---------------------------------------- void RWToggle::setRead() { // sout << locker << "\n setRead in " << name() << unlocker; ResetEvent(hWrite_); SetEvent(hRead_); readReady = true; } //----< put toggle in write mode >--------------------------------------- void RWToggle::setWrite() { // sout << locker << "\n setWrite in " << name() << unlocker; ResetEvent(hRead_); SetEvent(hWrite_); readReady = false; } //----< wait for reading >----------------------------------------------- void RWToggle::readWait() { WaitForSingleObject(hRead_,INFINITE); } //----< wait for writing >----------------------------------------------- void RWToggle::writeWait() { WaitForSingleObject(hWrite_,INFINITE); } //----< test ready to read - not used in this demonstration >------------ bool RWToggle::isReadyForReading() { return readReady; } //----< test ready to write - not used in this demonstration >----------- bool RWToggle::isReadyForWriting() { return !readReady; } //----< construct MMF manager >------------------------------------------ // // role is used for debugging, to see who is using what MMFmgr::MMFmgr(const std::string& name, size_t size, role r) : name_(name), size_(size), rwt_(name+"RWToggle",r), role_(r) { hMMF_ = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (int)size, name.c_str() ); if(hMMF_ == NULL) throw std::exception("\n\n can't create MMF\n\n"); pMMF_ = (char*)MapViewOfFile(hMMF_,FILE_MAP_ALL_ACCESS,0,0,size); } //----< close the MMF handle >------------------------------------------- MMFmgr::~MMFmgr() { CloseHandle(hMMF_); } //----< write a string to MMF and set toggle to read mode >-------------- void MMFmgr::putString(const std::string& str) { rwt_.writeWait(); if(str.size() > this->size_) throw std::exception("\n\n string size exceeds MMF size\n\n"); ::memcpy(pMMF_,str.c_str(),str.size()); *(pMMF_ + str.size()) = '\0'; rwt_.setRead(); } //----< read a string from MMF and set toggle to write mode >------------ std::string MMFmgr::getString() { rwt_.readWait(); std::string temp(pMMF_); rwt_.setWrite(); return temp; } //----< write a block of bytes to MMF - coming soon maybe >-------------- void MMFmgr::putBlock(Block blk) { throw std::exception("\n\n not implemented yet\n\n"); } //----< read a block of bytes from MMF - coming soon maybe >------------- Block MMFmgr::getBlock() { throw std::exception("\n\n not implemented yet\n\n"); } //----< test stub >------------------------------------------------------ #ifdef TEST_MMFMGR #include #include #include "..\Threads\threads.h" template std::string ToString(T t) { std::ostringstream out; out << t; return out.str(); } class threadProc : public Thread_Processing { public: threadProc(MMFmgr& mmf) : mmf_(mmf) {} threadProc* clone() const { return new threadProc(*this); } void run() { std::string msg; for(int i=0; i<20; ++i) { msg = "msg#"; msg += ToString(i); msg += " - through MMF"; mmf_.putString(msg); ::Sleep(10); } msg = "quit"; mmf_.putString(msg); } private: MMFmgr mmf_; }; void main() { try { RWToggle rwt("CSE775_Toggle",MMFmgr::client); MMFmgr mmf("CSE775_Map",1024,MMFmgr::client); mmf.putString("CSE775 string for Memory-Mapped File"); std::wcout << "\n " << mmf.getString().c_str() << "\n"; threadProc tp(mmf); Thread thrd(tp); thrd.start(); std::string msg = ""; while(msg != "quit") { msg = mmf.getString(); sout << "\n " << msg; } sout << "\n\n"; thrd.wait(); } catch(std::exception& ex) { sout << ex.what(); } } #endif