HCore SysSem

Files CCore/inc/sys/SysSem.h CCore/src/sys/SysSem.cpp

This part provides an OS backed semaphore.


#ifndef CCore_inc_sys_SysSem_h
#define CCore_inc_sys_SysSem_h
 
#include <CCore/inc/sys/SysError.h>

#include <CCore/inc/TimeScope.h>

namespace CCore {
namespace Sys {

/* classes */ 

struct Sem;

/* struct Sem */ 

struct Sem
 {
  // private
  
  ....

  // public
  
  ErrorType init(ulen count=0) noexcept;
  
  void exit() noexcept;
  
  void give() noexcept;
  
  void give_many(ulen count) noexcept;
  
  bool try_take() noexcept;
  
  void take() noexcept;
  
  bool take(MSec timeout) noexcept;

  bool take(TimeScope time_scope) noexcept;
 };
 
} // namespace Sys
} // namespace CCore
 
#endif

To create a semaphore you create an instance of the structure Sem and initialize it. Then you use its methods to do semaphore operations. Finally, you uninitialize the instance. Copying of the instances is prohibited. The private content of the structure is target-dependent. Semaphore methods, except init(), do not produce errors. They must be successful or call abort. For example, it must abort on the counter overflow.

init() initialize the semaphore with the given counter value. The error code is returned. If the object is successfully initialized, it must be uninitialized by the method exit().

exit() uninitialize the semaphore.

give() "gives" the semaphore counter (i.e. increments it). It may release a thread, blocked on the semaphore.

give_many() "gives" the semaphore counter many times (i.e. increases it) by the given value. It may release multiple threads, blocked on the semaphore.

try_take() tries to "take" the semaphore, i.e. tries to decrement its counter. If the counter is not null, it is decremented and the true is returned. Otherwise the false is returned.

take() "takes" the semaphore (i.e. decrements its counter). If the counter is null, the calling thread is blocked until the operation becomes possible. The thread may be blocked infinitely.

take(MSec timeout) and take(TimeScope time_scope) "takes" the semaphore (i.e. decrements its counter). But it blocks the calling thread up to the given timeout. If the semaphore was taken the method returns true. Otherwise the method returns false. It means the semaphore was not taken and the method call is finished because the timeout is expired.

Internally, Sem may contain only some "handle" and use global methods to deal with it:


struct Sem
 {
  // private data
  
  using Type = int ;
  
  Type handle;
  
  // private
  
  struct CreateType
   {
    Type handle;
    ErrorType error;
   };
   
  static CreateType Create(ulen count) noexcept;
  
  static void Destroy(Type handle) noexcept;
  
  static void Give(Type handle) noexcept;
  
  static void GiveMany(Type handle,ulen count) noexcept;
  
  static bool TryTake(Type handle) noexcept;
  
  static void Take(Type handle) noexcept;
  
  static bool Take(Type handle,MSec timeout) noexcept;

  static bool Take(Type handle,TimeScope time_scope) noexcept;
  
  // public
  
  ErrorType init(ulen count=0)
   {
    CreateType result=Create(count);
    
    handle=result.handle;
    
    return result.error;
   }
  
  void exit() { Destroy(handle); }
  
  void give() { Give(handle); }
  
  void give_many(ulen count) { GiveMany(handle,count); }
  
  bool try_take() { return TryTake(handle); }
  
  void take() { Take(handle); }
  
  bool take(MSec timeout) { return Take(handle,timeout); }

  bool take(TimeScope time_scope) { return Take(handle,time_scope); }
 };