/Src/Dependencies/Boost/boost/interprocess/sync/xsi/simple_xsi_semaphore.hpp

http://hadesmem.googlecode.com/ · C++ Header · 105 lines · 45 code · 16 blank · 44 comment · 11 complexity · 5ae0ced9a5f2f684b4d4481495d3da58 MD5 · raw file

  1. #ifndef BOOST_INTERPROCESS_SYNC_XSI_SIMPLE_XSI_SEMAPHORE_HPP
  2. #define BOOST_INTERPROCESS_SYNC_XSI_SIMPLE_XSI_SEMAPHORE_HPP
  3. /*
  4. * Provide an simpler and easier to understand interface to the System V
  5. * semaphore system calls. There are 7 routines available to the user:
  6. *
  7. * id = sem_create(key, initval); # create with initial value or open
  8. * id = sem_open(key); # open (must already exist)
  9. * sem_wait(id); # wait = P = down by 1
  10. * sem_signal(id); # signal = V = up by 1
  11. * sem_op(id, amount); # wait if (amount < 0)
  12. * # signal if (amount > 0)
  13. * sem_close(id); # close
  14. * sem_rm(id); # remove (delete)
  15. *
  16. * We create and use a 3-member set for the requested semaphore.
  17. * The first member, [0], is the actual semaphore value, and the second
  18. * member, [1], is a counter used to know when all processes have finished
  19. * with the semaphore. The counter is initialized to a large number,
  20. * decremented on every create or open and incremented on every close.
  21. * This way we can use the "adjust" feature provided by System V so that
  22. * any process that exit's without calling sem_close() is accounted
  23. * for. It doesn't help us if the last process does this (as we have
  24. * no way of getting control to remove the semaphore) but it will
  25. * work if any process other than the last does an exit (intentional
  26. * or unintentional).
  27. * The third member, [2], of the semaphore set is used as a lock variable
  28. * to avoid any race conditions in the sem_create() and sem_close()
  29. * functions.
  30. */
  31. #include <sys/ipc.h>
  32. #include <sys/sem.h>
  33. #include <errno.h>
  34. namespace boost {
  35. namespace interprocess {
  36. namespace xsi {
  37. // Create a semaphore with a specified initial value.
  38. // If the semaphore already exists, we don't initialize it (of course).
  39. // We return the semaphore ID if all OK, else -1.
  40. inline bool simple_sem_open_or_create(::key_t key, int initval, int &semid, int perm)
  41. {
  42. int id, semval;
  43. semid = -1;
  44. if (key == IPC_PRIVATE)
  45. return false; //not intended for private semaphores
  46. else if (key == (::key_t) -1)
  47. return false; //probably an ftok() error by caller
  48. again:
  49. if ((id = ::semget(key, 1, (perm & 0x01FF) | IPC_CREAT)) < 0)
  50. return false; //permission problem or tables full
  51. semid = id;
  52. return true;
  53. }
  54. /****************************************************************************
  55. * Remove a semaphore.
  56. * This call is intended to be called by a server, for example,
  57. * when it is being shut down, as we do an IPC_RMID on the semaphore,
  58. * regardless whether other processes may be using it or not.
  59. * Most other processes should use sem_close() below.
  60. */
  61. inline bool simple_sem_rm(int id)
  62. {
  63. if (::semctl(id, 0, IPC_RMID, 0) < 0)
  64. return false;
  65. return true;
  66. }
  67. /****************************************************************************
  68. * General semaphore operation. Increment or decrement by a user-specified
  69. * amount (positive or negative; amount can't be zero).
  70. */
  71. inline bool simple_sem_op(int id, int value, bool undo = true)
  72. {
  73. ::sembuf op_op[1] = {
  74. 0, 99, 0 // decrement or increment [0] with undo on exit
  75. // the 99 is set to the actual amount to add
  76. // or subtract (positive or negative)
  77. };
  78. if(undo){
  79. op_op[0].sem_flg = SEM_UNDO;
  80. }
  81. if ((op_op[0].sem_op = value) == 0)
  82. return false;
  83. if (::semop(id, &op_op[0], 1) < 0)
  84. return false;
  85. return true;
  86. }
  87. } //namespace xsi {
  88. } //namespace interprocess {
  89. } //namespace boost {