To implement this, you need a work queue (of numbers to be factored). The original thread starts by creating a pool of worker threads. It then reads inputs to create work items that it puts on the work queue, and the worker threads remove them. You also need a results queue. After a worker thread factors a number, it puts the result on that queue, and the original thread removes results from that queue and reports them.
The challenge with multi-threading is that threads run interleaved. A thread will randomly stop running
anywhere so that another thread can run, and
n threads can even run simultaneously if you have
n cores. This means that any data which is used by more than one thread must be protected by a critical region when it is being accessed. The critical region prevents one thread from trying to read data that another thread is in the middle of modifying (and which is therefore in an unstable state).
Given a choice between C and C++, I would use C++ for this because it has
<thread>
[
^],
<queue>
[
^], and
<mutex>
[
^], which should allow you to do this in a platform-independent way. Each queue should have its own mutex. The mutex must be acquired before accessing the queue and must be released immediately after accessing it. This prevents two threads from trying to handle the same work item, for example.
There are many ways to implement the function that worker threads execute. I don't know what has been covered in your course, so I will suggest a simple way. Other ways are arguably a bit better but more complicated. A worker thread basically has to do this:
while(true)
{
acquire the work queue mutex;
if(the work queue is empty)
{
release the work queue mutex;
sleep for 100 milliseconds;
}
else
{
pop an item off the work queue;
release the work queue mutex;
factor the number;
acquire the results queue mutex;
push the result onto the results queue;
release the results queue mutex;
}
}
After the original thread creates the worker threads, it will do much the same as this, except that it pushes items onto the work queue and pops them off the results queue. When it has read all the input and both queues are empty, it exits.