Mid Term Test Spring 1999
All questions worth 10 points - 70 points total (Average Grade 40, Median 42)
1) (Producer/Consumer Bounded Buffer Problem)
Because the Producer creates the Semaphores and Mapping File while the Consumer opens those objects created by the producer. If the consumer is started first, opening these objects will cause a failure. (3 points)
empty = OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE, "NTcourse.semaphore.empty"); // (3 points)
// replace above statement and
following loop with (4 points)
while((empty = OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,
"NTcourse.semaphore.empty") == NULL) {
sleep(1000); // not necessary but polite
}
2) In assignment one you were asked to use direct (random access) I/O to read message text bodies from the file when needed. However all messages were of a fixed size. Suppose you want to support variable length message text bodies in a solution where the topics are fixed length and stored in a "topics" file and the bodies are stored in a "bodies" file. Assume that all topics are stored in memory (done by inputMessages), but the message text body is only read as needed. Supply the following pieces of a solution to this problem
struct messages {
char topic[SIZE_TOPIC+1];
DWORD offset; // offset in bodies file where message starts, assume less than 4 gigabytes
int length; // length of message
int status; /// of this messages (used to find empty slots and mark deleted Messages)
} msgList[MAX_NUM_MSG]; // 2 points
void showMessage(int msgNum)
{
char * body; // 1 point
HANDLE bodiesFile;
DWORD nbytes;
bodiesFile = CreateFile("bodies",GENERIC_READ,0,0,
OPEN_EXISTING, 0, 0); // createfile or pass handle as parameter
body = new char[msgList[msgNum-1].length + 1); // allocate space (1 point)
SetFilePointer(bodiesFile, msgList[msgNum-1].offset, NULL, FILE_BEGIN); (2 points)
ReadFile(bodiesFile, body, msgList[msgNum-1].length + 1, &nBytes, 0); (1 points)
msgList[msgNum-1].status = MSG_OK;
CloseHandle(bodiesFile);
cout << "Topic: " << msgList[msgNum-1].topic << endl;
cout << "Text: " << body << endl; // 1 point
delete body[];
}
The bodies file is a kind of segmented memory system, so can apply various memory allocation strategies: (2 points)
3) You have decided to redo the CMessage object as an MFC object.
class CMessage: public CObject { // 2 point
public:
CMessage();
CMessage(const CMessage& Msg); // Copy constructor
~CMessage();
void SetTopic(const char * );
void GetTopic(char * thisTopic) const;
void SetText(const char *);
void GetText(char * thisMessage) const;
void Serialize(CArchive& ar); // 3 points
private:
char topic[SIZE_TOPIC+1]; // fixed string buffer for convenience
char text[SIZE_TEXT+1];
};
void CMessage::Serialize(CArchive& ar)
{
CObject::Serialize(ar); // 1 point
if (ar.IsStoring) // 2 points
ar << topic << text; //1 point
// the above is not equivalent to Write which writes a fixed size string
// also "<<" for CArchive is not overloaded for C-style strings
// It turns out that an equivalent function woudl require more information about CArchive
// than you had - the the above approximate solution is acceptable.
else
ar >> topic >> text; // 1 point
}
4) In the notes on "Hot Spots", colored rectangles were drawn under the buttons which simulated the actions of those buttons.
NO (windows objects are derived from CWnd (CRect is not). these
rectangles are merely drawn on the main window,
NO only window objects or objects derived from CCmdTarget can receive messages (2 points
each)
1) colored rectangles would not appear, although the buttons and
CEdit areas will paint themselves (3 points)
2) But clicking in these "invisible" rectangles would still simulate the button
click - no lose of function(3 points)
5) Answers the following questions about the use of the resource compiler.
No real effect - this is basically a comment to let the user know about the keyboard accelerator (4 points)
Actually I should have said the last argument and the following
function call. However I misread the program and placed LoadAccelTable as the last
argument of Create. What is interesting is that most students did also. - I accepted both
interpretations.
1) first argument loads main window menu resource - without this, no menu (3 points) - but
the accelerators still work!
2) second loads the accelerator table - without this, no accelerator keys (3 points)
6) Questions about starting a program.
main (3 points)
7) Questions about the structure of Version 4
void CMsgDlg::OnOK()
{
if (m_MsgID == NONE_SELECTED) m_MsgID = NEW_MSG; CDialog::OnOK(); }
class CMsgFolderApp : public CWinApp
{
public:
virtual BOOL InitInstance(); // everybody overrides this one
CMsgFolder msgFolder;
CMessage msg; // this can be deleted
};
class CMsgFolderApp : public CWinApp
{
public:
virtual BOOL InitInstance(); // everybody overrides this one
CMsgFolder msgFolder;
CMessage msg;
};
// Define the window object
class CMainWindow : public CFrameWnd
{
public:
CMainWindow();
~CMainWindow();
// Creates all the Message Edit Controls
protected:
// Handlers for MainFrame Menu Selections
afx_msg void OnOpenFolder();
afx_msg void OnCloseFolder();
afx_msg void OnEditMsg();
afx_msg void OnExit();
DECLARE_MESSAGE_MAP() // set up message map handling
private:
// Create OpenMessageFolder controls
CMsgDlg msgDlg; // this object can be deleted
};