it is my exam in 4 days and I just spoke to my lectuer and he has been extremely unclear about this part of the lecture and I really struggled along with many students how to understand this.
Basiclly, if you wanna implement Hoare monitor using semaphore, what is the sequences of steps involved?
Below is the pseudocode
]3
Update:
I am starting to get it now
so the 1st slide is for the process accessing the monitor
if you are the only one, then you call wait(mutex)
get into the monitor do your stuff and leave
if there is something waiting to get into the monitor then you up the next semaphore, that is the quene of waiting process to get into the semaphore. else if you are the only one in the monitor then you exit and up mutex so someone else can get into the mutex
for the 2nd slide with the wait(condition) and signal(condition)
when u wait(c):
c_count++ //number of process waiting for this condition, increment by one
if(next_count>0) up(next) //if number of waiting process that want t get into the monitor is more than zero, up(next), unblock one of the waiting process
else up(mutex) //if you are the only one then up mutex so someone else get in
down(c_sem) // block yourself to sleep
c_count-- //you wake up so number of process waiting for this condition decrement
for the signal(c) part:
if(c_count>0) // if number of process waiting for this condition is bigger than 0
next_counter++ //number of process wanting to get into the monitor increment by one
up(c_sem); // unblock one of the process waiting for this condition
down(next) //if a spot is available, down this otherwise get block and join list of waiting processes
next_count--; //you wake up and try to get into the monitor
Man, I can see why you are confused. The problem here is that this example merges two concepts.
A semaphore is a form of mutex. In the abstract, a mutex is just a variable that can be atomically incremented or decremented. Your up function increments. Your down function decrements event if multiple process are up'ing or down'ing at the same time. If you just make up equivalent to count = count + 1 you would get random results if multiple processes tried to increment at the same time.
In the real world (outside academia) a semaphore does more than just increment. You can wait on a semaphore as well.
So, if I do
real_world_down (semaphore)
My process decrements the semaphore. If no process (or thread) has locked the semaphore (usually = 0, with 1 being the starting point), my process continues. If another process has already locked the semaphore (value after down < 0), my process waits.
When the process that has locked the semaphore finishes and does
real_world_up (semaphore)
The operating system picks one of the waiting processes to run automatically.
Thus your Hoare monitor looks like
var
semaphore ;
Procedure Monitor
real_world_down (semaphore) ;
/* do whatever you want */
real_world_up (semaphore) ;
End ;
Or we could write it as:
var
semaphore ;
Procedure Monitor
lock (semaphore) ;
/* do whatever you want */
unlock (semaphore) ;
End ;
That's the monitor part. The part about your example that is confusing is that it is a poorly written lock/unlock using academic semaphores that just increment and decrement atomically and have no knowledge of who is waiting on them.
It's wait is equivalent to my lock.
It's equivalent to my unlock is totally FUed.
At this point I would leave as an exercise for you to create a lock function that will only allow one process/thread to acquire the lock using a pair of semaphores but will allow multiple processes to wait and, when unlocked, will allow one waiting process/thread to continue.
It needs an unlock function that will unlock the mutex pair to allow one process/thread to continue.
First of all - 2 hours is not really much time to calm you down, I guess - so I don't even try.
On the other hand: it's an exam, not a hackathon. Having said this, ... why don't you stick to the academic level that the slides of your professor have.
If you want a different version of explaining the fundamental work of the genius C.A.R. Hoare than have a look at this PowerPoint - you can read it all but the most important page for you should be page 15: MonitorPPT
And: in case you want to read the original paper after the exam - to prepare for fighting for points that you didn't get or just for fun - here it is: C.A.R. Hoare - Monitors: An Operating System
Structuring Concept
All the best for your exam, Tom!
Related
What's the best practice to achieve this :
1 - Thread for gathering data
2 - Wait for (1) to finish and render data
And those, indefinitely
while (true) {
thread tGatherData(getData); // Get data
tGatherData.join(); // Wait for data
thread tRender(render); // Render data
Sleep(3);
}
Using it like this doesn't sound like a good practice because it creates a new thread everytime right ?
How should I proceed ? Thanks
If you don't want to create thread on each iteration of your loop, you may want to start 2 threads: one for gathering information, second for printing it, and place your loop in both threads(you should remember about synchronization)
For example here I've created two threads: first for reading from console, second for printing. Synchronization is done by atomic. The program will stop execution, when it reads 0.
But, as good as I understand your code, you don't need second thread at all. All You need is to place your render function inside main thread. And your gathering function isn't asynchronous. It just create another thread and instantly start to wait for it's finishing, so your program should be single thread
I'm developing a C++14 Windows DLL on VS2015 that runs on all Windows version >= XP.
TL;DR
Is there a limit to the number of events, created with CreateEvent, with different names of course?
Background
I'm writing a thread pool class.
The class interface is simple:
void AddTask(std::function<void()> task);
Task is added to a queue of tasks and waiting workers (vector <thread>) activate the task when available.
Requirement
Wait (block) for a task for a little bit before continuing with the flow. Meaning, some users of ThreadPool, after calling AddTask, may want to wait for a while (say 1 second) for the task to end, before continuing with the flow. If the task is not done yet, they will continue with the flow anyways.
Problem
ThreadPool class cannot provide Wait interface. Not its responsibility.
Solution
ThreadPool will SetEvent when task is done.
Users of ThreadPool will wait (or not. depend on their need) for the event to be signaled.
So, I've changed the return value of ThreadPool::AddTask from void to int where int is a unique task ID which is essentially the name of the event to be singled when a task is done.
Question
I don't expect more than ~500 tasks but I'm afraid that creating hundreds of events is not possible or even a bad practice.
So is there a limit? or a better approach?
Of course there is a limit (if nothing else; at some point the system runs out of memory).
In reality, the limit is around 16 million per process.
You can read more details here: https://blogs.technet.microsoft.com/markrussinovich/2009/09/29/pushing-the-limits-of-windows-handles/
You're asking the wrong question. Fortunately you gave enough background to answer your real question. But before we get to that:
First, if you're asking what's the maximum number of events a process can open or a system can hold, you're probably doing something very very wrong. Same goes for asking what's the maximum number of files a process can open or what's the maximum number of threads a process can create.
You can create 50, 100, 200, 500, 1000... but where does it stop? If you're even considering creating that many of them that you have to ask about a limit, you're on the wrong track.
Second, the answer depends on too many implementation details: OS version, amount of RAM installed, registry settings, and maybe more. Other programs running also affect that "limit".
Third, even if you knew the limit - even if you could somehow calculate it at runtime based on all the relevant factors - it wouldn't allow you to do anything that you can't already do now.
Lets say you find out the limit is L and you have created exactly L events by now. Another task come in. What do you do? Throw away the task? Execute the task without signaling an event? Wait until there are fewer than L events and only then create an event and start executing the task? Crash the process?
Whatever you decide you can do it just the same when CreateEvent fails. All of this is completely pointless. And this is yet another indication that you're asking the wrong question.
But maybe the most wrong thing you're doing is saying "the thread pool class can't provide wait because it's not its responsibility, so lets have the thread pool class provide an event for each task that the thread pool will signal when the task ends" (in paraphrase).
It looks like by the end of the sentence you forgot the premise from the beginning: It's not the thread pool's responsibility!
If you want to wait for the task to finish have the task itself signal when it's done. There's no reason to complicate the thread pool because someone, sometimes want to wait on tasks. Signaling that the task is done is the task's job:
event evt; ///// this
thread_pool.queue([evt] {
// whatever
evt.signal(); ///// and this
});
auto reason = wait(evt, 1s);
if (reason == timeout) {
log("bummer");
}
The event class could be anything you want - a Windows event, and std::promise and std::future pair, or anything else.
This is so simple and obvious.
Complicating the thread pool infrastructure, taking up valuable system resources for nothing, and signaling synchronization primitives even when no one's listening just to save the two marked code lines above in the few cases where you actually want to wait for the task is unjustifiable.
I have a loop which basically calls this every few seconds (after the timeout):
while(true){
if(finished)
return;
switch(select(FD_SETSIZE, &readfds, 0, 0, &tv)){
case SOCKET_ERROR : report bad stuff etc; return;
default : break;
}
// do stuff with the incoming connection
}
So basically for every few seconds (which is specified by tv), it reactivates the listening.
This is run on thread B (not a main thread). There are times when I want to end this acceptor loop immediately from thread A (main thread), but seems like I have to wait until the time interval finishes..
Is there a way to disrupt the select function from another thread so thread B can quit instantly?
The easiest way is probably to use pipe(2) to create a pipe and add the read end to readfds. When the other thread wants to interrupt the select() just write a byte to it, then consume it afterward.
Yes, you create a connected pair of sockets. Then thread B writes to one side of socket and thread A adds the other side socket to select. So once B writes to socket A exits select, do not forget to read this byte from socket.
This is the most standard and common way to interrupt selects.
Notes:
Under Unix, use socketpair to create a pair of sockets, under windows it is little bit tricky but googling for Windows socketpair would give you samples of code.
Can't you just make the timeout sufficiently short (like 10ms or so?).
These "just create a dummy connection"-type solution seem sort of hacked. I personally think that if an application is well designed, concurrent tasks never have to be interrupted forcefully, the just has worker check often enough (this is also a reason why boost.threads do not have a terminate function).
Edit Made this answer CV. It is bad, but it might help other to understand why it is bad, which is explained in the comments.
You can use shutdown(Sock, SHUT_RDWR) call from main thread to come out of waiting select call which will also exit your another thread before the timeout so you don't need to wait till timeout expires.
cheers. :)
My process reads from a single queue tasks that need to be sent to several destinations.
We need to maintain order between the tasks (ie task that arrived in the queue at 00:00 needs to be sent before the task that arrived at 00:01) therefore we cannot use thread pool. Order needs to be maintained per destination.
One solution is to create a dedicated thread per destination. The main thread reads the
task from the queue and depending on the destination finds the correct thread.
This solution has a problem: if a worker thread is busy, the master thread would remain blocked, making the system slow. What I need is a new queue per thread. The master thread
shares the resources to the queues and the worker thread reads the new queues for incoming
messages...
I would like to share my thought with the SO community, and I am searching for a C/C++ solution close to me description. Is there a library that implements such model?
The design you want is fairly straightforward; I think you can probably write the code you need and get it working in an hour or two. Looking for a 3rd party library to implement this is probably overkill (unless I am misunderstanding the problem).
In particular, for each 'worker' thread, you need a FIFO data structure (e.g. std::queue), a Mutex, and a mechanism that the 'master' thread can use to signal the thread to wake up and check the data structure for new messages (e.g. a condition variable, or a semaphore, or even a socketpair that the worker blocks on reading, and the master can send a byte on to wake the worker up).
Then to send a task to a particular worker thread, the master would do something like this (pseudocode):
struct WorkerThreadData & workerThread = _workerThreads[threadIndexIWantToSendTo];
workerThread.m_mutex.Lock();
workerThread.m_incomingTasksList.push_back(theNewTaskObject);
workerThread.m_mutex.Unlock();
workerThread.m_signalMechanism.SignalThreadToWakeUp(); // make sure the worker looks at the task list!
... and each worker thread would have an event loop like this:
struct WorkerThreadData & myData = _workerThreads[myWorkerIndex];
TaskObject * taskObject;
while(1)
{
myData.m_signalMechanism.WaitForSignal(); // block until the main thread wakes me up
myData.m_mutex.Lock();
taskObject = (myData.m_incomingTasks.length() > 0) ? myData.m_incomingTasks.pop_front() : NULL;
myData.m_mutex.Unlock();
if (taskObject)
{
taskObject->DoTheWork();
delete taskObject;
}
}
This will never block the master thread (for any significant amount of time), since the Mutex is only held very briefly by anyone. In particular, the worker threads are not holding the mutex while they are working on a task object.
The "need to maintain order" all-but-directly states that you're going to be executing the tasks serially no matter how many threads you have. That being the case, you're probably best off with just one thread servicing the requests.
You could gain something if the requirement is a bit looser than that -- for example, if all the tasks for one destination need to remain in order, but there's no ordering requirement for tasks with different destinations. If this is the case, then your solution of a master queue sending tasks to an input queue for each individual thread sounds like quite a good one.
Edit:
Specifying the number of threads/mutexes dynamically is pretty easy. For example, to take the number from the command line, you could do something on this order (leaving out error and sanity checking for the moment):
std::vector<pthread_t> threads;
int num_threads = atoi(argv[1]);
threads.resize(num_threads);
for (int i=0; i<num_threads; i++)
pthread_create(&threads[i], NULL, thread_routine, NULL);
At the moment I am using a producer consumer model for the rendering portion of a realtime graphics application. The consumer will continually look for data in our queue(infinite loop); however I am fearful that this may cause my simulation to get out of sync of the main loop. I think this is the fast producer slow consumer problem - compounded by the fact that the simulation is restrained to a certain amount of time.
Question - what is the best method to keep this all in balance and make sure the consumer has enough time to finish, but also that the simulation does not move to the next frame before we are finished rendering our current frame(or at least be able to detect this and skip rendering the next frame - or interrupt the current frame being rendered) I am currently just interrupting and joining after each consumer is finished
Second Question: if you look at the code below you will see that I am currently just calling interrupt and join after adding rendering jobs to the queue - this allows the thread all the time it needs to complete its operation, and to respond to the interrupt when finished. How can I then reuse threads in a thread pool after interrupt_all and join_all are called? (i.e. if i call drawNextFrame again)
The producer is part of the main thread of execution (I don't think this affects anything)
pseudo code:
void renderSystem::init()
create queue to hold work;
create consumer threads of type RenderConsumer set to watch our queue;
add threads to thread_pool of consumers called 'RenderThreads'
void renderSystem::drawNextFrame()
for each thread in 'RenderThreads' divy up work;
add work assignment to queue;
//RenderThreads will now successfully start pulling data from our queue
renderThreads.interupt_all();
renderThreads.join_all();
int main()
renderer = renderSystem class;
renderer.init()
while(not_gameover)
renderer.drawNextFrame();
doOtherCoolStuff();
profit(?)
return(0)
if you need to look at the consumer class see below:
pseudo code:
RenderConsumer::operator () ()
while(true)
try to dequeue from queue
//digest any packet we get
for each ( pixel in packet )
computePrettyStuff()
//we are now done with packet that we got
this_thread::interruption_point();
I tried to make this simple and quick to digest, thank you for your time
#1. I would do this by counting the amount in the queue after each render. If it too high, then either
a. Dump the queue
b. Set a boolean variable to false
That variable will be shared between the threads, and when the producer sees that it is false, it begins waiting on a condition variable. The consumer then notifies the producer when the queue is down to an acceptable level again.
#2. Probably not possible with join_all, as the postcondition to join_all is
Every thread in the group has
terminated.
according to the reference.
It might however be possible, using barriers instead of join_all, but then you would have to find a way to provide them data, which would invariably end up needing some more shared variables.