I get this error message, and I don't seem to understand it. What does it mean by ANSI C++ forbids implicit conversion from `void *' in assignment? . And the Fork function only takes the function name and a number
Thread::Fork(VoidFunctionPtr func, int arg)
Error message:
../threads/threadtest.cc: In function `void ServerThread(int)':
../threads/threadtest.cc:72: ANSI C++ forbids implicit conversion from `void *' in assignment
../threads/threadtest.cc:78: implicit declaration of function `int WorkerThread(...)'
REGION:
72 - 78:
nextReq = list -> Remove();
//check till the end
while (nextReq != NULL)
{
WorkerThread(&nextReq);
code:
#include "copyright.h"
#include "system.h"
#include <stdio.h>
#include "request.h"
extern void serve(char *url);
//GLOBAL VARIABLE LIST
List *list;
//----------------------------------------------------------------------
// ThreadTest
// read file and serve urls
//----------------------------------------------------------------------
void
ClientThread(int request)
{
const int sz = 50;
char url[sz];
FILE *fp = fopen("url.txt", "r");
if (!fp)
printf(" Cannot open file url.txt!\n");
else {
int pos = 0;
char c = getc(fp);
while (c != EOF || pos == sz - 1) {
if (c == '\n') {
url[pos] = '\0';
serve(url);
pos = 0;
//Store necessary information in a Request object for each request.
Request req(url, request, 1);
Request *reqq = &req; //req points to the object
list->Append(reqq);
}
else {
url[pos++] = c;
}
c = getc(fp);
}
fclose(fp);
}
}
//----------------------------------------------------------------------
void
ServerThread(int which)
{
Request *nextReq;
//gets the first node off the list
nextReq = list -> Remove();
//check till the end
while (nextReq != NULL)
{
WorkerThread(nextReq);
}
}
//----------------------------------------------------------------------
void
WorkerThread (Request req)
{
serve(req.url);
currentThread -> Yield();
}
//----------------------------------------------------------------------
void
ThreadTest()
{
DEBUG('t', "Entering SimpleTest");
printf("THREAD TEST");
//Thread *c = new Thread("client thread");
Thread *s = new Thread("server thread");
s->Fork(ServerThread, 1);
ClientThread(0);
}
This appears to be one of the offending lines:
nextReq = list -> Remove();
It appears that list->Remove()
returns a void *
. C++ requires a cast to turn this into another pointer (C does not). So change this to:
nextReq = static_cast<Request *>(list -> Remove());
(Alternatively, consider making List
a template class so you can avoid these kinds of unsafe casts. Based on your code, the STL class std::queue<Request>
should fulfill your needs here.)
The second offending line is your call to WorkerThread()
before it is defined. You need to add a prototype for the function prior to your definition of ServerThread()
. Otherwise the compiler does not know what its prototype is, and it should complain once it reaches the real definition of ServerThread()
that it does not match the prototype that it deduced earlier.
void WorkerThread(Request);
void
ServerThread(int which)
{
// ...
(Or, since WorkerThread()
does not call ServerThread()
, you could just swap the order of the definitions of the two functions to resolve the problem.)
Further, note that this code is bad:
Request req(url, request, 1);
Request *reqq = &req; //req points to the object
list->Append(reqq);
You construct an object and then push a pointer to the stack-allocated object onto a list. When ClientThread()
returns, this object will be destroyed and you are left with a pointer to an object that no longer exists. Using this pointer will trigger undefined behavior. Consider instead allocating a new Request
on the heap by using Request *reqq = new Request(url, request, 1);
(but don't forget to delete
the object after you process it).
Or, better yet, use std::queue<Request>
as I suggested earlier -- then you can just queue.emplace(url, request, 1);
. But note that you do need a way to synchronize access to the queue from multiple threads.