gold-threads.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // gold-threads.h -- thread support for gold -*- C++ -*-
  2. // Copyright (C) 2006-2022 Free Software Foundation, Inc.
  3. // Written by Ian Lance Taylor <iant@google.com>.
  4. // This file is part of gold.
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 3 of the License, or
  8. // (at your option) any later version.
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software
  15. // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  16. // MA 02110-1301, USA.
  17. // gold can be configured to support threads. If threads are
  18. // supported, the user can specify at runtime whether or not to
  19. // support them. This provides an interface to manage locking
  20. // accordingly.
  21. // Lock
  22. // A simple lock class.
  23. #ifndef GOLD_THREADS_H
  24. #define GOLD_THREADS_H
  25. namespace gold
  26. {
  27. class Condvar;
  28. class Once_initialize;
  29. class Initialize_lock_once;
  30. // The interface for the implementation of a Lock.
  31. class Lock_impl
  32. {
  33. public:
  34. Lock_impl()
  35. { }
  36. virtual
  37. ~Lock_impl()
  38. { }
  39. virtual void
  40. acquire() = 0;
  41. virtual void
  42. release() = 0;
  43. };
  44. // A simple lock class.
  45. class Lock
  46. {
  47. public:
  48. Lock();
  49. ~Lock();
  50. // Acquire the lock.
  51. void
  52. acquire()
  53. { this->lock_->acquire(); }
  54. // Release the lock.
  55. void
  56. release()
  57. { this->lock_->release(); }
  58. private:
  59. // This class can not be copied.
  60. Lock(const Lock&);
  61. Lock& operator=(const Lock&);
  62. friend class Condvar;
  63. Lock_impl*
  64. get_impl() const
  65. { return this->lock_; }
  66. Lock_impl* lock_;
  67. };
  68. // RAII for Lock.
  69. class Hold_lock
  70. {
  71. public:
  72. Hold_lock(Lock& lock)
  73. : lock_(lock)
  74. { this->lock_.acquire(); }
  75. ~Hold_lock()
  76. { this->lock_.release(); }
  77. private:
  78. // This class can not be copied.
  79. Hold_lock(const Hold_lock&);
  80. Hold_lock& operator=(const Hold_lock&);
  81. Lock& lock_;
  82. };
  83. class Hold_optional_lock
  84. {
  85. public:
  86. Hold_optional_lock(Lock* lock)
  87. : lock_(lock)
  88. {
  89. if (this->lock_ != NULL)
  90. this->lock_->acquire();
  91. }
  92. ~Hold_optional_lock()
  93. {
  94. if (this->lock_ != NULL)
  95. this->lock_->release();
  96. }
  97. private:
  98. Hold_optional_lock(const Hold_optional_lock&);
  99. Hold_optional_lock& operator=(const Hold_optional_lock&);
  100. Lock* lock_;
  101. };
  102. // The interface for the implementation of a condition variable.
  103. class Condvar_impl
  104. {
  105. public:
  106. Condvar_impl()
  107. { }
  108. virtual
  109. ~Condvar_impl()
  110. { }
  111. virtual void
  112. wait(Lock_impl*) = 0;
  113. virtual void
  114. signal() = 0;
  115. virtual void
  116. broadcast() = 0;
  117. };
  118. // A simple condition variable class. It is always associated with a
  119. // specific lock.
  120. class Condvar
  121. {
  122. public:
  123. Condvar(Lock& lock);
  124. ~Condvar();
  125. // Wait for the condition variable to be signalled. This should
  126. // only be called when the lock is held.
  127. void
  128. wait()
  129. { this->condvar_->wait(this->lock_.get_impl()); }
  130. // Signal the condition variable--wake up at least one thread
  131. // waiting on the condition variable. This should only be called
  132. // when the lock is held.
  133. void
  134. signal()
  135. { this->condvar_->signal(); }
  136. // Broadcast the condition variable--wake up all threads waiting on
  137. // the condition variable. This should only be called when the lock
  138. // is held.
  139. void
  140. broadcast()
  141. { this->condvar_->broadcast(); }
  142. private:
  143. // This class can not be copied.
  144. Condvar(const Condvar&);
  145. Condvar& operator=(const Condvar&);
  146. Lock& lock_;
  147. Condvar_impl* condvar_;
  148. };
  149. // A class used to do something once. This is an abstract parent
  150. // class; any actual use will involve a child of this.
  151. class Once
  152. {
  153. public:
  154. Once();
  155. virtual
  156. ~Once()
  157. { }
  158. // Call this function to do whatever it is. We pass an argument
  159. // even though you have to use a child class because in some uses
  160. // setting the argument would itself require a Once class.
  161. void
  162. run_once(void* arg);
  163. // This is an internal function, which must be public because it is
  164. // run by an extern "C" function called via pthread_once.
  165. void
  166. internal_run(void* arg);
  167. protected:
  168. // This must be implemented by the child class.
  169. virtual void
  170. do_run_once(void* arg) = 0;
  171. private:
  172. // True if we have already run the function.
  173. bool was_run_;
  174. #if defined(ENABLE_THREADS) && defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
  175. // Internal compare-and-swap lock on was_run_;
  176. uint32_t was_run_lock_;
  177. #endif
  178. // The lock to run the function only once.
  179. Once_initialize* once_;
  180. };
  181. // A class used to initialize a lock exactly once, after the options
  182. // have been read. This is needed because the implementation of locks
  183. // depends on whether we've seen the --threads option. Before the
  184. // options have been read, we know we are single-threaded, so we can
  185. // get by without using a lock. This class should be an instance
  186. // variable of the class which has a lock which needs to be
  187. // initialized.
  188. class Initialize_lock : public Once
  189. {
  190. public:
  191. // The class which uses this will have a pointer to a lock. This
  192. // must be constructed with a pointer to that pointer.
  193. Initialize_lock(Lock** pplock)
  194. : pplock_(pplock)
  195. { }
  196. // Initialize the lock. Return true if the lock is now initialized,
  197. // false if it is not (because the options have not yet been read).
  198. bool
  199. initialize();
  200. protected:
  201. void
  202. do_run_once(void*);
  203. private:
  204. // A pointer to the lock pointer which must be initialized.
  205. Lock** const pplock_;
  206. };
  207. } // End namespace gold.
  208. #endif // !defined(GOLD_THREADS_H)