| 
 | 
 | 
 
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   | 
		 
		
			
				
				
				
					
						
						Tom1
						 Messages: 1305 Registered: March 2007 
						
					 | 
					Ultimate 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    | 
		 
		
			
				
				
				
					
						
						Tom1
						 Messages: 1305 Registered: March 2007 
						
					 | 
					Ultimate 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    | 
		 
		
			
				
				
				
					
						
						Tom1
						 Messages: 1305 Registered: March 2007 
						
					 | 
					Ultimate Contributor  | 
					 | 
		 
		 
	 | 
 
	
		Hi, 
 
I think this is now up to Mirek now...   
 
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 #52867 is a reply to message #52865] | 
			Thu, 19 December 2019 14:38    | 
		 
		
			
				
				
				
					
						
						Tom1
						 Messages: 1305 Registered: March 2007 
						
					 | 
					Ultimate 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
		
		
		
 |  
	| 
		
	 | 
 
 
 |  
	| 
		
 |  
	| 
		
 |  
	| 
		
 |  
	| 
		
 |   
Goto Forum:
 
 Current Time: Tue Nov 04 03:47:17 CET 2025 
 Total time taken to generate the page: 0.05147 seconds 
 |   
 |  
  |