Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » Community » Coffee corner » What is the best way to create a Semaphore with timeout?
What is the best way to create a Semaphore with timeout? [message #52857] Tue, 17 December 2019 09:49 Go to next message
Tom1
Messages: 674
Registered: March 2007
Contributor
Hi,

I need a Semaphore with Wait(int timeout_ms); What is the best way (in terms of efficiency) to implement this timeout functionality?

Using SetTimeCallback() to Release() the Semaphore is not an option in non-GUI environment. Another thread Sleeping for the specified amount of time and then calling Release feels a bit inefficient.

(For the background: I'm building a FIFO using BiVector and wish to get minimal latency and overhead for the operation.)

Best regards,

Tom
Re: What is the best way to create a Semaphore with timeout? [message #52858 is a reply to message #52857] Tue, 17 December 2019 10:49 Go to previous messageGo to next message
Tom1
Messages: 674
Registered: March 2007
Contributor
Hi,

I took a look at Core and found that Semaphore is really just an abstraction of the OS semaphore.

Now the question is: Would it be possible to change Semaphore code in a way that adds support for timeout? Looking at the code reveals that Windows and Linux/Posix could support Wait(timeout) with minimal changes, but I'm not so sure about OSX.

Best regards,

Tom
Re: What is the best way to create a Semaphore with timeout? [message #52859 is a reply to message #52858] Tue, 17 December 2019 11:53 Go to previous messageGo to next message
Tom1
Messages: 674
Registered: March 2007
Contributor
Hi,

I think this is now up to Mirek now... Wink

I have made the needed additions to Semaphore for implementing timeout on Wait.

Here's working code for Windows and Linux:

Mt.h:

...
class Semaphore : NoCopy {
#ifdef PLATFORM_WIN32
	HANDLE     handle;
#elif PLATFORM_OSX
	dispatch_semaphore_t    sem;
#else
	sem_t      sem;
#endif

public:
	bool       Wait(int timeout_ms); // Added for timeout - returns true if semaphore was signaled, false otherwise
	void       Wait();
	void       Release();
#ifdef PLATFORM_WIN32
	void       Release(int n);
#endif

	Semaphore();
	~Semaphore();
};
...



Mt.cpp:

...

// For Windows:
bool Semaphore::Wait(int timeout_ms)
{
	return WaitForSingleObject(handle, timeout_ms<0 ? INFINITE : timeout_ms) == WAIT_OBJECT_0 ? true : false;
}

...

// For Linux:
bool Semaphore::Wait(int timeout_ms)
{
	if(timeout_ms<0){
		Wait();
		return true;
	}
	
	struct timespec until;
	clock_gettime(CLOCK_REALTIME, &until);
	
	until.tv_sec+=timeout_ms/1000;
	timeout_ms%=1000;
	until.tv_nsec+=timeout_ms*1000000;
	until.tv_sec+=until.tv_nsec/1000000000;
	until.tv_nsec%=1000000000;
	
	return sem_timedwait(&sem,&until)==-1 ? false : true;
}
...


Maybe someone with a Mac could take a look at the OSX code for the same. From what I found on the web, it looks like it could be something like this for OSX:

...
bool Semaphore::Wait(int timeout_ms)
{ 
	if(timeout_ms<0){
		dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
		return true;
	}
	return dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, 1000000 * timeout_ms)) == 0 ? true : false;
}
...


I hope this makes it to the Core.

Best regards,

Tom
Re: What is the best way to create a Semaphore with timeout? [message #52864 is a reply to message #52859] Thu, 19 December 2019 11:38 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12179
Registered: November 2005
Ultimate Member
Thank you, makes sense, in Core now. I have just removed <0 rule, that is imo not necessarry as we have "infinite" version already.

Now time to add that to ConditionVariable too.
Re: What is the best way to create a Semaphore with timeout? [message #52865 is a reply to message #52864] Thu, 19 December 2019 12:59 Go to previous messageGo to next message
Tom1
Messages: 674
Registered: March 2007
Contributor
Hi Mirek,

Thanks!

While on the subject, why not add the timeout functionality to ConditionVariable too... Would you like me to figure out the details or are you already working on it?

Best regards,

Tom
Re: What is the best way to create a Semaphore with timeout? [message #52866 is a reply to message #52865] Thu, 19 December 2019 13:40 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12179
Registered: November 2005
Ultimate Member
Tom1 wrote on Thu, 19 December 2019 12:59
Hi Mirek,

Thanks!

While on the subject, why not add the timeout functionality to ConditionVariable too... Would you like me to figure out the details or are you already working on it?

Best regards,

Tom


Sure, done.
Re: What is the best way to create a Semaphore with timeout? [message #52867 is a reply to message #52865] Thu, 19 December 2019 14:38 Go to previous messageGo to next message
Tom1
Messages: 674
Registered: March 2007
Contributor
Hi!

That was fast! Thanks Mirek!!

Now to the Fifo implementation. Does this look right from the point of mutex synchronization? I know this 'appears to work when testing' but I'm new with ConditionVariable, so I'm a bit uncertain if my usage of it is correct. I.e. Will multiple receiving threads calling StringFifo::Get() be correctly served so that each and every String will get read exactly once?

class StringFifo: public BiVector<String>{
	ConditionVariable cv;
	Mutex mtx;
	
public:
	StringFifo(){
		
	}
	
	void Put(const String &s){
		mtx.Enter();
		AddTail(s);
		cv.Signal();
		mtx.Leave();
	}
	
	String Get(int timeout_ms=-1){
		mtx.Enter();
		if(GetCount() || (cv.Wait(mtx,timeout_ms) && GetCount())){
			String r=PopHead();
			mtx.Leave();
			return r;
		}
		else{
			mtx.Leave();
			return String::GetVoid();
		}
	}
};


Thanks and best regards,

Tom
Re: What is the best way to create a Semaphore with timeout? [message #52868 is a reply to message #52867] Thu, 19 December 2019 17:05 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12179
Registered: November 2005
Ultimate Member
Tom1 wrote on Thu, 19 December 2019 14:38
Hi!

That was fast! Thanks Mirek!!

Now to the Fifo implementation. Does this look right from the point of mutex synchronization? I know this 'appears to work when testing' but I'm new with ConditionVariable, so I'm a bit uncertain if my usage of it is correct. I.e. Will multiple receiving threads calling StringFifo::Get() be correctly served so that each and every String will get read exactly once?

class StringFifo: public BiVector<String>{
	ConditionVariable cv;
	Mutex mtx;
	
public:
	StringFifo(){
		
	}
	
	void Put(const String &s){
		mtx.Enter();
		AddTail(s);
		cv.Signal();
		mtx.Leave();
	}
	
	String Get(int timeout_ms=-1){
		mtx.Enter();
		if(GetCount() || (cv.Wait(mtx,timeout_ms) && GetCount())){
			String r=PopHead();
			mtx.Leave();
			return r;
		}
		else{
			mtx.Leave();
			return String::GetVoid();
		}
	}
};


Thanks and best regards,

Tom


Sounds good.

Unfortunately, I have removed -1 logic from your code, so that will make it more complicate. I guess I will put it back after all.
Re: What is the best way to create a Semaphore with timeout? [message #52869 is a reply to message #52868] Thu, 19 December 2019 21:44 Go to previous messageGo to next message
Tom1
Messages: 674
Registered: March 2007
Contributor
Ok, thanks Mirek!

Best regards,

Tom
Re: What is the best way to create a Semaphore with timeout? [message #52968 is a reply to message #52869] Wed, 22 January 2020 14:44 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12179
Registered: November 2005
Ultimate Member
Tom1 wrote on Thu, 19 December 2019 21:44
Ok, thanks Mirek!

Best regards,

Tom


-1 logic is back...
Re: What is the best way to create a Semaphore with timeout? [message #52969 is a reply to message #52968] Wed, 22 January 2020 14:48 Go to previous message
Tom1
Messages: 674
Registered: March 2007
Contributor
Thanks! Smile

Best regards,

Tom
Previous Topic: Linux binary application distribution options?
Goto Forum:
  


Current Time: Mon Feb 17 08:43:49 CET 2020

Total time taken to generate the page: 0.01368 seconds