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