Implementing a printer spooler - c++

We have an assignment in which we have to implement a printer spooler using linked lists. I have used the list from STL to implement everything. I can get the program to send the print command and maintain status of documents. The problem is I don't know how to mimic/send a dummy print command so the document gets printed. If I use Sleep() there is a delay in the whole program.while I want printing on backhand and others users to have access to the program.
Any help will be appreciated regarding my problem thanks.

In a REAL print spooler, either there are multiple threads (or in Unix, maybe a fork) or the system uses a "wait for several objects" type approach, and when there is something to print, a portion of the document is sent to the printer, set up so that when that portion is "consumed", a waitable object is "ready". Then the spooler waits for something to happen (either a new job or the printed). When the wait is completed, it determines what happened. If it's a new print job, queue it, if it's "some printing completed", it checks if that's the last of the printing and completes the job, or sends more stuff to the printer.
In pseudocdoe it may look something like this:
for(;;)
{
what = wait_for_work();
switch (what)
{
case new_job:
add_new_job();
break;
case print_write_done:
if (document_complete)
remove_current_job();
else
send_more_from_current_job();
break;
case spooler_terminate:
exit(0);
default:
print_error_message();
}
}
Obviously, without seeing your code, it's hard to say how you should implement it. But one could have a timer to simulate the "document being printed in small chunks", say, 10KB is consumed every 100ms, for example.

Related

c threads - why does mmsystem (using mciSendString) not play the sound file?

I want my game to play some sfx. At the beginning, I open some mp3 file mciSendString("open Muzle.mp3 alias Muzle");.
My problem is that mciSendString("play Muzle from 0"); still causes a little lag and the game has to play the sounds frequently.
In another question, I read that using threads will solve the problem. I'm completely new to using threads. The problem now is that the sound doesn't play :p . I verified that the thread runs properly by giving a cout at the end.
I have this function now:
void Shout(string SoundName){
string FNstr;
wstring FNwstr;
FNstr = "play " + SoundName + " from 0";
FNwstr.assign(FNstr.begin(), FNstr.end());
mciSendString(FNwstr.c_str(), NULL, 0, NULL);
Sleep(2000);
cout << "Test woi\n";
}
(I tried without Sleep too. I wonder if I need it, because if the thread reaches the end, it might get deleted and the sound terminated... I'm not sure how threads or the mmsystem work)
If I simply call this Shout() function, it will play the sound, do the Sleep(2000), and then cout. Everything worked fine. But I have to use threads, so I try:
thread(Shout, "Muzle");
and I got error: abort() has been called. I figured out I may need to detach the thread:
thread t(Shout, "Muzle");
t.detach();
With this, everything looked to work fine (after 2 seconds, I see the "Test woi" printed on the console), but no sound was played.
Hmm, so thanks for reading everything ^.^ . Do you know how to solve this problem?
You should probably have ONE permanent thread that:
1. Waits for the sound to finish before moving on (assuming that is the way you want it to work). You can probably just use the "wait" option to do that.
2. When not playing a sound, waits for a command to play the next sound - using a pipe to send messages to the thread would be one such solution, but you could use other methods.

FindNextPrinterChangeNotification returns NULL for ppPrinterNotifyInfo

I'm stuck on problem were I would like to ask for some help:
I have the task to print some files of different types using ShellExecuteEx with the "print" verb and need to guarantee print order of all files. Therefore I use FindFirstPrinterChangeNotification and FindNextPrinterChangeNotification to monitor the events PRINTER_CHANGE_ADD_JOB and PRINTER_CHANGE_DELETE_JOB using two different threads in the background which I start before calling ShellExecuteEx as I don't know anything about the application which will print the files etc. The only thing I know is that I'm the only one printing and which file I print. My solution seems to work well, my program successfully recognizes the event PRINTER_CHANGE_ADD_JOB for my file, I even verify that this event is issued for my file by checking what is give to me as additional info by specifying JOB_NOTIFY_FIELD_DOCUMENT.
The problem now is with the event PRINTER_CHANGE_DELETE_JOB, where I don't get any addition info about the print job, though my logic is exactly the same for both events: I've written one generic thread function which simply gets executed with the event it is used for. My thread is recognizing the PRINTER_CHANGE_DELETE_JOB event, but on each call to FindNextPrinterChangeNotification whenever this event occured I don't get any addition data in ppPrinterNotifyInfo. This works for the start event, though, I verified using my logs and the debugger. But with PRINTER_CHANGE_DELETE_JOB the only thing I get is NULL.
I already searched the web and there are some similar questions, but most of the time related to VB or simply unanswered. I'm using a C++ project and as my code works for the ADD_JOB-event I don't think I'm doing something completely wrong. But even MSDN doesn't mention this behavior and I would really like to make sure that the DELETE_JOB event is the one for my document, which I can't without any information about the print job. After I get the DELETE_JOB event my code doesn't even recognize other events, which is OK because the print job is done afterwards.
The following is what I think is the relevant notification code:
WORD jobNotifyFields[1] = {JOB_NOTIFY_FIELD_DOCUMENT};
PRINTER_NOTIFY_OPTIONS_TYPE pnot[1] = {JOB_NOTIFY_TYPE, 0, 0, 0, 1, jobNotifyFields};
PRINTER_NOTIFY_OPTIONS pno = {2, 0, 1, pnot};
HANDLE defaultPrinter = PrintWaiter::openDefaultPrinter();
HANDLE changeNotification = FindFirstPrinterChangeNotification( defaultPrinter,
threadArgs->event,
0, &pno);
[...]
DWORD waitResult = WAIT_FAILED;
while ((waitResult = WaitForSingleObject(changeNotification, threadArgs->wfsoTimeout)) == WAIT_OBJECT_0)
{
LOG4CXX_DEBUG(logger, L"Irgendein Druckereignis im Thread zum Warten auf Ereignis " << LogStringConv(threadArgs->event) << L" erkannt.");
[...]
PPRINTER_NOTIFY_INFO notifyInfo = NULL;
DWORD events = 0;
FindNextPrinterChangeNotification(changeNotification, &events, NULL, (LPVOID*) &notifyInfo);
if (!(events & threadArgs->event) || !notifyInfo || !notifyInfo->Count)
{
LOG4CXX_DEBUG(logger, L"unpassendes Ereignis " << LogStringConv(events) << L" ignoriert");
FreePrinterNotifyInfo(notifyInfo);
continue;
}
[...]
I would really appreciate if anyone could give some hints on why I don't get any data regarding the print job. Thanks!
https://forums.embarcadero.com/thread.jspa?threadID=86657&stqc=true
Here's what I think is going on:
I observe two events in two different threads for the start and end of each print job. With some debugging and logging I recognized that FindNextPrinterChangeNotification doesn't always return only the two distinct events I've notified for, but some 0-events in general. In those cases FindNextPrinterChangeNotification returns 0 as the events in pdwChange. If I print a simple text file using notepad.exe I only get one event for creation of the print job with value 256 for pdwChange and the data I need in notifyInfo to compare my printed file name against and comparing both succeeds. If I print a pdf file using current Acrobat Reader 11 I get two events, one has pdwChange as 256, but gives something like "local printdatafile" as the name of the print job started, which is obviously not the file I printed. The second event has a pdwChange of 0, but the name of the print job provided in notifyInfo is the file name I used to print. As I use FreePDF for testing pruproses, I think the first printer event is something internal to my special setup.
The notifications for the deletion of a print job create 0 events, too. This time those are sent before FindNextPrinterChangeNotification returns 1024 in pdwChange, and timely very close after the start of the print job. In this case the exactly one generated 0 event contains notifyInfo with a document name which equals the file name I started printing. After the 0 event there's exactly one additional event with pdwChange of 1024, but without any data for notifyInfo.
I think Windows is using some mechanism which provides additional notifications for the same event as 0 events after the initial event has been fired with it's real value the user notified with, e.g. 256 for PRINTER_CHANGE_ADD_JOB. On the other hand it seems that some 0 events are simply fired to provide data for an upcoming event which then gets the real value of e.g. 1024 for PRINTER_CHANGE_DELETE_JOB, but without anymore data because that has already been delivered to the event consumer with a very early 0 event. Something like "Look, there's more for the last events." and "Look, something is going to happen with the data I already provide now." Implementing such an approach my prints now seem to work as expected.
Of course what I wrote doesn't fit to what is documented for FindNextPrinterChangeNotification, but it makes a bit of sense to me. ;-)
You're not checking for overflows or errors.
The documentation for FindNextPrinterChangeNotification says this:
If the PRINTER_NOTIFY_INFO_DISCARDED bit is set in the Flags member of
the PRINTER_NOTIFY_INFO structure, an overflow or error occurred, and
notifications may have been lost. In this case, no additional
notifications will be sent until you make a second
FindNextPrinterChangeNotification call that specifies
PRINTER_NOTIFY_OPTIONS_REFRESH.
You need to check for that flag and do as described above, and you should also be checking the return code from FindNextPrinterChangeNotification.

program stops after execvp( command.argv[0], command.argv)

I am writing a small shell program that takes a command and executes it. If the user enters a not valid command the if statement returns a -1. If the command is correct it executes the command, however once it executes the command the program ends. What am I doing wrong that is does not execute the lines of code after it? I have tested execvp( command.argv[0], command.argv) with ls and cat commands so I am pretty sure it works. Here is my code.
int shell(char *cmd_str ){
int commandLength=0;
cmd_t command;
commandLength=make_cmd(cmd_str, command);
cout<< commandLength<<endl;
cout << command.argv[0]<< endl;
if( execvp( command.argv[0], command.argv)==-1)
//if the command it executed nothing runs after this line
{
commandLength=-1;
}else
{
cout<<"work"<<endl;
}
cout<< commandLength<<endl;
return commandLength;
}
From man page of execvp(3)
The exec() family of functions replaces the current process image with
a new process image
So your current process image is overwritten with the image of your command! Hence you need to use a fork+exec combination always so that your command executes in the child process and your current process continues safely as a parent!
On a lighter note I want to illustrate the problem with a picture as a picture speaks a thousand words. No offence intended :) :)
From the documentation on exec
The exec() family of functions replaces the current process image with a new process image. The functions described in this manual page are front-ends for execve(2). (See the manual page for > execve(2) for further details about the replacement of the current process image.)
If you want your process to continue, this is not the function you want to use.
#Pavan - Just for nit-pickers like myself, technically the statement "current process is gone" is not true. It's still the same process, with the same pid, just overwritten with a different image (code, data etc).

Scanf with Signals

I have a signal that blocks SIGINT and basically says "Sorry, you can't quit.\n"
The issue is this can occur during a scanf.
When this occurs during a scanf, scanf takes in the printf as input.
How can I do a printf that will cause scanf to basically hit the enter key automatically. I don't care that I am getting bad input. I just want to programatically finish that scanf with a printf or something else.
Process:
scanf("get stuff")
-> User is able to enter stuff in.
-> SIGINT occurs and goes to my handler.
-> Handler says "Blah blah blah" to stdout.
-> Scanf has taken this blah blah blah and is waiting for more input.
How do I make it so that when I return scanf is finished (don't care what it has gathered I just want it to continue without user help).
EDIT: if I send two signals then the scanf terminates. I want to emulate the ending of the scanf somehow programatically.
Your question suggests you are confused - or perhaps English is not your native language.
I have a signal that blocks SIGINT and basically says "Sorry, you can't quit.\n"
What you might have is a signal handler that is set to respond to SIGINT. Further, you might be using the 'signal()' function to set the handler - but you should be aiming to use the POSIX standard 'sigaction()' function to set the handler instead.
The issue is this can occur during a scanf.
In context, 'this' is presumably an interrupt signal, typed by the user who wishes to stop your program. Be cautious about stopping people exiting a program with an interrupt signal; if you don't let them do that, they will be more brutal. That might mean they'll generate SIGQUIT (and perhaps a core dump) instead; if you block that too, there are a number of other tricks they can try until they get to the ultimate 'kill -9 pid' which your program will get no chance to react to.
When this occurs during a scanf, scanf takes in the printf as input.
This is confused...you are presumably implying that the output from a 'printf()' statement (presumably the one that says "You can't quit") is then being seen as input to the 'scanf()'? Which seems pretty improbable... It would require a very, very weird setup on the I/O of the process, and I'm still not convinced it can happen.
How can I do a printf that will cause scanf to basically hit the enter key automatically. I don't care that I am getting bad input. I just want to programatically finish that scanf with a printf or something else.
There are several possibilities - it depends in part on the O/S you are using (even if it is POSIX.) I don't use 'scanf()'; I find it too difficult to control. If your system resumes the reads after the interrupt handler returns, then you will have a difficult time. Sometimes, though, 'scanf()' will stop short and return the number of items it has processed. If the 'scanf()' you have does not terminate, then you will need to think about interposing a 'sigsetjmp()' in a function that simply calls 'setjmp()' and then invokes your function that calls 'scanf()'. Then your signal handler can use 'siglongjmp()' to return to that intermediate function:
sigjmp_buf trap;
int intermediary(int argument)
{
if (sigsetjmp(trap) == 0)
{
function_calling_scanf(argument);
return 0; // Success
}
// Report failure
return -1;
}
Your description continues:
Process:
scanf("get stuff") -> User is able to enter stuff in.
-> SIGINT occurs and goes to my handler.
-> Handler says "Blah blah blah" to stdout.
-> Scanf has taken this blah blah blah and is waiting for more input.
How do you know that scanf has read the 'blah blah blah'? It seems very, very improbable to me.
How do I make it so that when I return scanf is finished (don't care what it has gathered I just want it to continue without user help).
Use sigsetjmp().
EDIT: if I send two signals then the scanf terminates. I want to emulate the ending of the scanf somehow programmatically.
This is what indicates that you are using 'signal()' to set your signal handler and not 'sigaction()'. With 'signal()', when the interrupt occurs, the signal handler is set back to the default. With 'sigaction()', you have to request that behaviour; by default, the received signal (SIGINT) is blocked for the duraction and the signal handler remains in effect. If a second interrupt occurs while the first is running, the second is held up until the first handler returns (at which point the handler will be re-entered).
Don't use scanf as its buffering or retry code may get in the way. If you use a read(2) call it should return -1 with an errno of EINTR. Scanf may see that error and retry the read. You can always sscanf the data from the raw read.
This is assuming that QNX is POSIX compliant for read and you don't have the source for scanf for inspection.

Deleting And Reconstructing Singleton in C++

I have an application which runs on a controlling hardware connected with different sensors. On loading the application, it checks the individual sensors one by one to see whether there is proper communication with the sensor according to predefined protocol or not.
Now, I have implemented the code for checking the individual sensor communication as a singleton thread and following is the run function, it used select system call and pipe for interprocess communication to signal the end of thread.
void SensorClass::run()
{
mFdWind=mPort->GetFileDescriptor();
fd_set readfs;
int max_fd = (mFdWind > gPipeFdWind[0] ? mFdWind : gPipeFdWind[0]) + 1;
int res;
mFrameCorrect=false;
qDebug("BEFORE WHILE");
while(true)
{
qDebug("\n IN WHILE LOOP");
usleep(50);
FD_ZERO(&readfs);
FD_SET(mFdWind,&readfs);
FD_SET(gPipeFdWind[0],&readfs);
res=select(max_fd,&readfs,NULL,NULL,NULL);
if(res < 0)
perror("Select Failed");
else if(res == 0)
puts("TIMEOUT");
else
{
if(FD_ISSET(mFdWind,&readfs))
{
puts("*************** RECEIVED DATA ****************");
mFrameCorrect=false;
FlushBuf();
//int n=mPort->ReadPort(mBuf,100);
int n=mPort->ReadPort(mBuf,100);
if(n>0)
{
Count++;
QString str((const char*)mBuf);
//qDebug("\n %s",qPrintable(str));
//See if the Header of the frame is valid
if(IsHeaderValid(str))
{
if( (!IsCommaCountOk(str)) || (!IsChecksumOk(str,mBuf)) || (!CalculateCommaIndexes(str)) )
{
qDebug("\n not ok");
mFrameCorrect=false;
} //if frame is incorrect
else
{
qDebug("\n OK");
mFrameCorrect=true;
}//if frame is correct(checksum etc are ok)
}//else if header is ok
}//if n > 0
}//if data received FD_ISSET
if(FD_ISSET(gPipeFdWind[0],&readfs))
break;
}//end nested else res not <= 0
}//infinite loop
}
The above thread is run started from the main GUI thread. This runs fine. The problem is I have given an option to the user to retest the subsystem at will. For this I delete the singleton instance using
delete SensorClass::instance();
and then restart the singleton using
SensorClass::instace()->start();
The problem is this time the control comes out of while loop in run() function immedeately upon entering the while loop, my guess is the pipe read has again read from the write pipe which was written to the last time. I have tried to use the fflush() to clear out the I/O but no luck.
My question is
Am I thinking on the right track?
If yes then how do we clear out the pipes?
If not can anyone suggest why is the selective retest not working?
Thanks in advance..
fflush clears the output buffer. If you want to clear the input buffer, you're going to need to read the data or seek to the end.
I'm not convinced the "Singleton" pattern is appropriate. There are other ways of ensuring at most one instance for each piece of hardware. What if you later want multiple threads, each working with a different sensor?
Let's assume that you're creating this thread by inheriting from QThread (which you don't specify). From the documentation of QThread::~QThread ():
Note that deleting a QThread object will not stop the execution of the thread it represents. Deleting a running QThread (i.e. isFinished() returns false) will probably result in a program crash.
So the statement delete SensorClass::instance(); is probably a really, really bad idea. In particular, it's going to be tough making any sense of this program's behavior given this flaw. Before continuing, you might want to find a way to remove the instance and ensure that the thread goes away, too.
Another problem comes to mind. When you run delete SensorClass::instance(), you get rid of some object (on the heap, one hopes). Who tells the singleton holder that its object is gone? E.g. so that the next call to SensorClass::instance() knows it needs to allocate another instance? Is this handled properly in SensorClass::~SensorClass?
Suppose that's not a problem. That likely means that the pointer to the instance is held in a global variable (or, e.g. a class level static member). It probably doesn't matter for this situation, but is access to that member properly synchronized? I.e. is there a mutex that's locked for each access to it?
You really don't want to run your initialization in thread. That is issue number one that dramatically complicates your problem and which is the kind of thing for some reason no one points out.
Just make the initialization its own function, then have a guard variable and lock, and have everything that uses it separately initialize it when they start up.
So you're signaling by writing something to the pipe, and the pipe is only created once - i.e. reused in the later threads?
Read the signaling away from the pipe. Assuming you signal by writing a single byte, then instead of just breaking out, you'd do something like (NB, no error checking etc below):
if(FD_ISSET(gPipeFdWind[0],&readfs)) {
char c;
read(gPipeFdWind[0], &c, 1);
break;
}
There are also Qt classes for handling socket I/O, e.g. QTcpSocket, which would make the code not only cleaner, also more cross-platform. Or at least QSocketNotifier to abstract the select away.